@truffle/compile-solidity
Version:
Compiler helper and artifact manager for Solidity files
343 lines (291 loc) • 10.5 kB
JavaScript
const debug = require("debug")("compile:test:test_supplier");
const fse = require("fs-extra");
const path = require("path");
const assert = require("assert");
const Resolver = require("@truffle/resolver");
const { Compile } = require("@truffle/compile-solidity");
const Config = require("@truffle/config");
const { findOne } = require("./helpers");
function waitSecond() {
return new Promise(resolve => setTimeout(() => resolve(), 1250));
}
describe("CompilerSupplier", function () {
describe("integration", function () {
this.timeout(40000);
let oldPragmaPinSource; // 0.4.15
let oldPragmaFloatSource; // ^0.4.15
let version4PragmaSource; // ^0.4.21
let version5PragmaSource; // ^0.5.0
let version6PragmaSource; // ^0.6.0
let versionLatestPragmaSource; // Currently: ^0.8.0
let compileConfig;
const options = {
contracts_directory: "",
solc: "",
quiet: true
};
before("get code", async function () {
const oldPragmaPin = await fse.readFile(
path.join(__dirname, "./sources/v0.4.15/OldPragmaPin.sol"),
"utf-8"
);
const oldPragmaFloat = await fse.readFile(
path.join(__dirname, "./sources/v0.4.x/OldPragmaFloat.sol"),
"utf-8"
);
const version4Pragma = await fse.readFile(
path.join(__dirname, "./sources/v0.4.x/NewPragma.sol"),
"utf-8"
);
const version5Pragma = await fse.readFile(
path.join(__dirname, "./sources/v0.5.x/Version5Pragma.sol"),
"utf-8"
);
const version6Pragma = await fse.readFile(
path.join(__dirname, "./sources/v0.6.x/Version6Pragma.sol"),
"utf-8"
);
const versionLatestPragma = await fse.readFile(
path.join(__dirname, "./sources/v0.8.x/Version8Pragma.sol"), //update when necessary
"utf-8"
);
oldPragmaPinSource = { "OldPragmaPin.sol": oldPragmaPin };
oldPragmaFloatSource = { "OldPragmaFloat.sol": oldPragmaFloat };
version4PragmaSource = { "NewPragma.sol": version4Pragma };
version5PragmaSource = { "Version5Pragma.sol": version5Pragma };
version6PragmaSource = { "Version6Pragma.sol": version6Pragma };
versionLatestPragmaSource = { "Version8Pragma.sol": versionLatestPragma }; //update when necessary
});
it("compiles w/ default solc if no compiler specified (float)", async function () {
const defaultOptions = Config.default().merge(options);
const { compilations } = await Compile.sources({
sources: version5PragmaSource,
options: defaultOptions
});
const Version5Pragma = findOne(
"Version5Pragma",
compilations[0].contracts
);
assert(Version5Pragma.contractName === "Version5Pragma");
});
it("compiles w/ remote solc when options specify release (pinned)", async function () {
options.compilers = {
solc: {
version: "0.4.15",
settings: {}
}
};
const config = new Config().with(options);
const { compilations } = await Compile.sources({
sources: oldPragmaPinSource,
options: config
});
const OldPragmaPin = findOne("OldPragmaPin", compilations[0].contracts);
assert(OldPragmaPin.contractName === "OldPragmaPin");
});
it("compiles w/ remote solc when options specify prerelease (float)", async function () {
this.timeout(20000);
// An 0.4.16 prerelease for 0.4.15
options.compilers = {
solc: {
version: "0.4.16-nightly.2017.8.9+commit.81887bc7",
settings: {}
}
};
const config = Config.default().merge(options);
const { compilations } = await Compile.sources({
sources: oldPragmaFloatSource,
options: config
});
const OldPragmaFloat = findOne(
"OldPragmaFloat",
compilations[0].contracts
);
assert(OldPragmaFloat.contractName === "OldPragmaFloat");
});
it("compiles w/ local path solc when options specify path", async function () {
const pathToSolc = path.join(__dirname, "../node_modules/solc/index.js");
options.compilers = {
solc: {
version: pathToSolc
}
};
const localPathOptions = Config.default().merge(options);
const { compilations } = await Compile.sources({
sources: version6PragmaSource,
options: localPathOptions
});
const Version6Pragma = findOne(
"Version6Pragma",
compilations[0].contracts
);
assert(Version6Pragma.contractName === "Version6Pragma");
});
it("caches releases and uses them if available", async function () {
let initialAccessTime;
let finalAccessTime;
const compilerCacheDirectory = path.resolve(
Config.getTruffleDataDirectory(),
"compilers/node_modules"
);
const expectedCache = path.resolve(
compilerCacheDirectory,
"soljson-v0.4.21+commit.dfe3193c.js"
);
// Delete if it's already there.
if (await fse.exists(expectedCache)) await fse.unlink(expectedCache);
options.compilers = {
solc: { version: "0.4.21" }
};
const cachedOptions = Config.default().merge(options);
// Run compiler, expecting solc to be downloaded and cached.
await Compile.sources({
sources: version4PragmaSource,
options: cachedOptions
});
assert(await fse.exists(expectedCache), "Should have cached compiler");
// Get cached solc access time
initialAccessTime = (await fse.stat(expectedCache)).atime.getTime();
// Wait a second and recompile, verifying that the cached solc
// got accessed / ran ok.
await waitSecond();
const { compilations } = await Compile.sources({
sources: version4PragmaSource,
options: cachedOptions
});
finalAccessTime = (await fse.stat(expectedCache)).atime.getTime();
const NewPragma = findOne("NewPragma", compilations[0].contracts);
assert(NewPragma.contractName === "NewPragma", "Should have compiled");
// atime is not getting updatd on read in CI.
if (!process.env.TEST) {
assert(
initialAccessTime < finalAccessTime,
"Should have used cached compiler"
);
}
});
describe("native / docker [ @native ]", function () {
it("compiles with native solc", async function () {
options.compilers = {
solc: {
version: "native"
}
};
const nativeSolcOptions = Config.default().merge(options);
const { compilations } = await Compile.sources({
sources: versionLatestPragmaSource,
options: nativeSolcOptions
});
const VersionLatestPragma = findOne(
"Version8Pragma",
compilations[0].contracts
); //update when necessary
assert(VersionLatestPragma.compiler.version.includes("0.8.")); //update when necessary
assert(
VersionLatestPragma.contractName === "Version8Pragma", //update when necessary
"Should have compiled"
);
});
it("compiles with dockerized solc", async function () {
options.compilers = {
solc: {
version: "0.4.22",
docker: true
}
};
const dockerizedSolcOptions = Config.default().merge(options);
const expectedVersion = "0.4.22+commit.4cb486ee.Linux.g++";
const { compilations } = await Compile.sources({
sources: version4PragmaSource,
options: dockerizedSolcOptions
});
const NewPragma = findOne("NewPragma", compilations[0].contracts);
assert(NewPragma.compiler.version === expectedVersion);
assert(NewPragma.contractName === "NewPragma", "Should have compiled");
});
it("resolves imports correctly when using built solc", async function () {
const paths = [];
paths.push(path.join(__dirname, "./sources/v0.4.x/ComplexOrdered.sol"));
paths.push(path.join(__dirname, "./sources/v0.4.x/InheritB.sol"));
let options = {
compilers: {
solc: {
version: "0.4.22",
docker: true,
settings: {
optimizer: {
enabled: false,
runs: 200
}
}
}
},
quiet: true,
solc: "",
contracts_build_directory: path.join(__dirname, "./build"),
contracts_directory: path.join(__dirname, "./sources/v0.4.x"),
working_directory: __dirname,
paths: paths
};
options.resolver = new Resolver(options);
options = Config.default().merge(options);
const { compilations } = await Compile.sourcesWithDependencies({
paths,
options
});
const ComplexOrdered = findOne(
"ComplexOrdered",
compilations[0].contracts
);
// This contract imports / inherits
assert(
ComplexOrdered.contractName === "ComplexOrdered",
"Should have compiled"
);
});
it("errors if running dockerized solc without specifying an image", async function () {
options.compilers = {
solc: {
version: undefined,
docker: true,
settings: {}
}
};
compileConfig = Config.default().merge(options);
let error;
try {
await Compile.sources({
sources: version4PragmaSource,
options: compileConfig
});
} catch (err) {
error = err;
}
assert(error);
assert(error.message.includes("option must be"));
});
it("errors if running dockerized solc when image does not exist locally", async function () {
const imageName = "fantasySolc.7777555";
options.compilers = {
solc: {
version: imageName,
docker: true,
settings: {}
}
};
compileConfig = Config.default().merge(options);
let error;
try {
await Compile.sources({
sources: version4PragmaSource,
options: compileConfig
});
} catch (err) {
error = err;
}
assert(error);
assert(error.message.includes(imageName));
});
});
});
});