Skip to content

Commit beaed8c

Browse files
authored
Merge pull request #190 from ethereum/support-old-soljson
Support running compiler unit tests on older (read: <0.4.9) compilers
2 parents 640e98d + fb59742 commit beaed8c

File tree

3 files changed

+120
-52
lines changed

3 files changed

+120
-52
lines changed

test/package.js

Lines changed: 99 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,34 @@ const tape = require('tape');
22
const semver = require('semver');
33
const solc = require('../index.js');
44

5+
function getBytecode (output, fileName, contractName) {
6+
try {
7+
var outputContract;
8+
if (semver.lt(solc.semver(), '0.4.9')) {
9+
outputContract = output.contracts[contractName];
10+
} else {
11+
outputContract = output.contracts[fileName + ':' + contractName];
12+
}
13+
return outputContract['bytecode'];
14+
} catch (e) {
15+
return '';
16+
}
17+
}
18+
19+
function getBytecodeStandard (output, fileName, contractName) {
20+
try {
21+
var outputFile;
22+
if (semver.lt(solc.semver(), '0.4.9')) {
23+
outputFile = output.contracts[''];
24+
} else {
25+
outputFile = output.contracts[fileName];
26+
}
27+
return outputFile[contractName]['evm']['bytecode']['object'];
28+
} catch (e) {
29+
return '';
30+
}
31+
}
32+
533
tape('Version and license', function (t) {
634
t.test('check version', function (st) {
735
st.equal(typeof solc.version(), 'string');
@@ -21,19 +49,32 @@ tape('Compilation', function (t) {
2149
t.test('single files can be compiled', function (st) {
2250
var output = solc.compile('contract x { function g() {} }');
2351
st.ok('contracts' in output);
24-
st.ok(':x' in output.contracts);
25-
st.ok('bytecode' in output.contracts[':x']);
26-
st.ok(output.contracts[':x'].bytecode.length > 0);
52+
var bytecode = getBytecode(output, '', 'x');
53+
st.ok(bytecode);
54+
st.ok(bytecode.length > 0);
2755
st.end();
2856
});
2957
t.test('invalid source code fails properly', function (st) {
3058
var output = solc.compile('contract x { this is an invalid contract }');
59+
if (semver.lt(solc.semver(), '0.1.4')) {
60+
st.ok(output.error.indexOf('Parser error: Expected identifier') !== -1);
61+
st.end();
62+
return;
63+
}
3164
st.plan(3);
3265
st.ok('errors' in output);
3366
// Check if the ParserError exists, but allow others too
3467
st.ok(output.errors.length >= 1);
3568
for (var error in output.errors) {
36-
if (output.errors[error].indexOf('ParserError') !== -1) {
69+
// Error should be something like:
70+
// ParserError
71+
// Error: Expected identifier
72+
// Parser error: Expected identifier
73+
if (
74+
output.errors[error].indexOf('ParserError') !== -1 ||
75+
output.errors[error].indexOf('Error: Expected identifier') !== -1 ||
76+
output.errors[error].indexOf('Parser error: Expected identifier') !== -1
77+
) {
3778
st.ok(true);
3879
}
3980
}
@@ -52,13 +93,12 @@ tape('Compilation', function (t) {
5293
'cont.sol': 'import "lib.sol"; contract x { function g() { L.f(); } }'
5394
};
5495
var output = solc.compile({sources: input});
55-
st.ok('contracts' in output);
56-
st.ok('cont.sol:x' in output.contracts);
57-
st.ok('lib.sol:L' in output.contracts);
58-
st.ok('bytecode' in output.contracts['cont.sol:x']);
59-
st.ok('bytecode' in output.contracts['lib.sol:L']);
60-
st.ok(output.contracts['cont.sol:x'].bytecode.length > 0);
61-
st.ok(output.contracts['lib.sol:L'].bytecode.length > 0);
96+
var x = getBytecode(output, 'cont.sol', 'x');
97+
st.ok(x);
98+
st.ok(x.length > 0);
99+
var L = getBytecode(output, 'lib.sol', 'L');
100+
st.ok(L);
101+
st.ok(L.length > 0);
62102
st.end();
63103
});
64104

@@ -80,13 +120,12 @@ tape('Compilation', function (t) {
80120
}
81121
}
82122
var output = solc.compile({sources: input}, 0, findImports);
83-
st.ok('contracts' in output);
84-
st.ok('cont.sol:x' in output.contracts);
85-
st.ok('lib.sol:L' in output.contracts);
86-
st.ok('bytecode' in output.contracts['cont.sol:x']);
87-
st.ok('bytecode' in output.contracts['lib.sol:L']);
88-
st.ok(output.contracts['cont.sol:x'].bytecode.length > 0);
89-
st.ok(output.contracts['lib.sol:L'].bytecode.length > 0);
123+
var x = getBytecode(output, 'cont.sol', 'x');
124+
var L = getBytecode(output, 'lib.sol', 'L');
125+
st.ok(x);
126+
st.ok(x.length > 0);
127+
st.ok(L);
128+
st.ok(L.length > 0);
90129
st.end();
91130
});
92131

@@ -111,7 +150,8 @@ tape('Compilation', function (t) {
111150
for (var error in output.errors) {
112151
// Error should be something like:
113152
// cont.sol:1:1: ParserError: Source "lib.sol" not found: File not found
114-
if (output.errors[error].indexOf('ParserError') !== -1 && output.errors[error].indexOf('File not found') !== -1) {
153+
// cont.sol:1:1: Error: Source "lib.sol" not found: File not found
154+
if (output.errors[error].indexOf('Error') !== -1 && output.errors[error].indexOf('File not found') !== -1) {
115155
st.ok(true);
116156
}
117157
}
@@ -155,7 +195,8 @@ tape('Compilation', function (t) {
155195
for (var error in output.errors) {
156196
// Error should be something like:
157197
// cont.sol:1:1: ParserError: Source "lib.sol" not found: File not supplied initially.
158-
if (output.errors[error].indexOf('ParserError') !== -1 && output.errors[error].indexOf('File not supplied initially.') !== -1) {
198+
// cont.sol:1:1: Error: Source "lib.sol" not found: File not supplied initially.
199+
if (output.errors[error].indexOf('Error') !== -1 && output.errors[error].indexOf('File not supplied initially.') !== -1) {
159200
st.ok(true);
160201
}
161202
}
@@ -280,6 +321,14 @@ tape('Compilation', function (t) {
280321
st.end();
281322
});
282323
t.test('compiling standard JSON (using wrapper)', function (st) {
324+
// Example needs support for compileJSONMulti
325+
// FIXME: add test for wrapper without multiple files
326+
if (semver.lt(solc.semver(), '0.1.6')) {
327+
st.skip('Not supported by solc <0.1.6');
328+
st.end();
329+
return;
330+
}
331+
283332
var input = {
284333
'language': 'Solidity',
285334
'settings': {
@@ -299,17 +348,13 @@ tape('Compilation', function (t) {
299348
}
300349
};
301350

302-
function bytecodeExists (output, fileName, contractName) {
303-
try {
304-
return output.contracts[fileName][contractName]['evm']['bytecode']['object'].length > 0;
305-
} catch (e) {
306-
return false;
307-
}
308-
}
309-
310351
var output = JSON.parse(solc.compileStandardWrapper(JSON.stringify(input)));
311-
st.ok(bytecodeExists(output, 'cont.sol', 'x'));
312-
st.ok(bytecodeExists(output, 'lib.sol', 'L'));
352+
var x = getBytecodeStandard(output, 'cont.sol', 'x');
353+
st.ok(x);
354+
st.ok(x.length > 0);
355+
var L = getBytecodeStandard(output, 'lib.sol', 'L');
356+
st.ok(L);
357+
st.ok(L.length > 0);
313358
st.end();
314359
});
315360
});
@@ -328,17 +373,24 @@ tape('Loading Legacy Versions', function (t) {
328373
});
329374

330375
tape('Linking', function (t) {
376+
// FIXME: all the linking tests require compileJSONMulti support,
377+
// create test cases which have all files in a single source and could run with 0.1.3
378+
if (semver.lt(solc.semver(), '0.1.6')) {
379+
t.skip('Not supported by solc <0.1.6');
380+
t.end();
381+
return;
382+
}
383+
331384
t.test('link properly', function (st) {
332385
var input = {
333386
'lib.sol': 'library L { function f() returns (uint) { return 7; } }',
334387
'cont.sol': 'import "lib.sol"; contract x { function g() { L.f(); } }'
335388
};
336389
var output = solc.compile({sources: input});
337-
st.ok('contracts' in output);
338-
st.ok('cont.sol:x' in output.contracts);
339-
st.ok('bytecode' in output.contracts['cont.sol:x']);
340-
st.ok(output.contracts['cont.sol:x'].bytecode.length > 0);
341-
var bytecode = solc.linkBytecode(output.contracts['cont.sol:x'].bytecode, { 'lib.sol:L': '0x123456' });
390+
var bytecode = getBytecode(output, 'cont.sol', 'x');
391+
st.ok(bytecode);
392+
st.ok(bytecode.length > 0);
393+
bytecode = solc.linkBytecode(bytecode, { 'lib.sol:L': '0x123456' });
342394
st.ok(bytecode.indexOf('_') < 0);
343395
st.end();
344396
});
@@ -349,11 +401,10 @@ tape('Linking', function (t) {
349401
'cont.sol': 'import "lib.sol"; contract x { function g() { L.f(); } }'
350402
};
351403
var output = solc.compile({sources: input});
352-
st.ok('contracts' in output);
353-
st.ok('cont.sol:x' in output.contracts);
354-
st.ok('bytecode' in output.contracts['cont.sol:x']);
355-
st.ok(output.contracts['cont.sol:x'].bytecode.length > 0);
356-
var bytecode = solc.linkBytecode(output.contracts['cont.sol:x'].bytecode, { });
404+
var bytecode = getBytecode(output, 'cont.sol', 'x');
405+
st.ok(bytecode);
406+
st.ok(bytecode.length > 0);
407+
bytecode = solc.linkBytecode(bytecode, { });
357408
st.ok(bytecode.indexOf('_') >= 0);
358409
st.end();
359410
});
@@ -364,12 +415,11 @@ tape('Linking', function (t) {
364415
'cont.sol': 'import "lib.sol"; contract x { function g() { L.f(); } }'
365416
};
366417
var output = solc.compile({sources: input});
367-
st.ok('contracts' in output);
368-
st.ok('cont.sol:x' in output.contracts);
369-
st.ok('bytecode' in output.contracts['cont.sol:x']);
370-
st.ok(output.contracts['cont.sol:x'].bytecode.length > 0);
418+
var bytecode = getBytecode(output, 'cont.sol', 'x');
419+
st.ok(bytecode);
420+
st.ok(bytecode.length > 0);
371421
st.throws(function () {
372-
solc.linkBytecode(output.contracts['cont.sol:x'].bytecode, { 'lib.sol:L': '' });
422+
solc.linkBytecode(bytecode, { 'lib.sol:L': '' });
373423
});
374424
st.end();
375425
});
@@ -380,11 +430,10 @@ tape('Linking', function (t) {
380430
'cont.sol': 'import "lib.sol"; contract x { function g() { L1234567890123456789012345678901234567890.f(); } }'
381431
};
382432
var output = solc.compile({sources: input});
383-
st.ok('contracts' in output);
384-
st.ok('cont.sol:x' in output.contracts);
385-
st.ok('bytecode' in output.contracts['cont.sol:x']);
386-
st.ok(output.contracts['cont.sol:x'].bytecode.length > 0);
387-
var bytecode = solc.linkBytecode(output.contracts['cont.sol:x'].bytecode, { 'lib.sol:L1234567890123456789012345678901234567890': '0x123456' });
433+
var bytecode = getBytecode(output, 'cont.sol', 'x');
434+
st.ok(bytecode);
435+
st.ok(bytecode.length > 0);
436+
bytecode = solc.linkBytecode(bytecode, { 'lib.sol:L1234567890123456789012345678901234567890': '0x123456' });
388437
st.ok(bytecode.indexOf('_') < 0);
389438
st.end();
390439
});

test/translate.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ tape('Version string to Semver translator', function (t) {
1919
st.equal(versionToSemver('0.1.1-6ff4cd6b/RelWithDebInfo-Emscripten/clang/int'), '0.1.1+commit.6ff4cd6b');
2020
st.end();
2121
});
22+
t.test('Old style 0.1.2', function (st) {
23+
st.equal(versionToSemver('0.1.2-5c3bfd4b*/.-/clang/int'), '0.1.2+commit.5c3bfd4b');
24+
st.end();
25+
});
26+
t.test('Broken 0.1.3', function (st) {
27+
st.equal(versionToSemver('0.1.3-0/.-/clang/int linked to libethereum-0.9.92-0/.-/clang/int'), '0.1.3');
28+
st.end();
29+
});
2230
t.test('Old style 0.2.0', function (st) {
2331
st.equal(
2432
versionToSemver('0.2.0-e7098958/.-Emscripten/clang/int linked to libethereum-1.1.1-bbb80ab0/.-Emscripten/clang/int'),

translate.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@
22
/// Old style: 0.3.6-3fc68da5/Release-Emscripten/clang
33
/// 0.3.5-371690f0/Release-Emscripten/clang/Interpreter
44
/// 0.2.0-e7098958/.-Emscripten/clang/int linked to libethereum-1.1.1-bbb80ab0/.-Emscripten/clang/int
5+
/// 0.1.3-0/.-/clang/int linked to libethereum-0.9.92-0/.-/clang/int
6+
/// 0.1.2-5c3bfd4b*/.-/clang/int
57
/// 0.1.1-6ff4cd6b/RelWithDebInfo-Emscripten/clang/int
68
/// New style: 0.4.5+commit.b318366e.Emscripten.clang
79
function versionToSemver (version) {
810
// FIXME: parse more detail, but this is a good start
9-
var parsed = version.match(/^([0-9]+\.[0-9]+\.[0-9]+)-([0-9a-f]{8})\/.*$/);
11+
var parsed = version.match(/^([0-9]+\.[0-9]+\.[0-9]+)-([0-9a-f]{8})[/*].*$/);
1012
if (parsed) {
1113
return parsed[1] + '+commit.' + parsed[2];
1214
}
15+
if (version.indexOf('0.1.3-0') !== -1) {
16+
return '0.1.3';
17+
}
1318
// assume it is already semver compatible
1419
return version;
1520
}
@@ -56,7 +61,13 @@ function translateJsonCompilerOutput (output) {
5661
var ret = {};
5762

5863
ret['errors'] = [];
59-
translateErrors(ret['errors'], output['errors']);
64+
var errors;
65+
if (output['error']) {
66+
errors = [ output['error'] ];
67+
} else {
68+
errors = output['errors'];
69+
}
70+
translateErrors(ret['errors'], errors);
6071

6172
ret['contracts'] = {};
6273
for (var contract in output['contracts']) {

0 commit comments

Comments
 (0)