-
Notifications
You must be signed in to change notification settings - Fork 43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
composer: add initial version #75
Conversation
Pretty sure it must because this is how the testground SDK gets all the information. |
Drive by: not entirely certain as I'm not following closely but might need testground/testground#1505 to pair with testground/testground#1522 |
@@ -0,0 +1,11 @@ | |||
id,muxer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naive question, will there be an additional csv for security protocol TLS/Noise, or is that being handled differently?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will be another file, i.e. sec.csv
:
id,protocol
rust-master,noise
rust-master, tls
rust-0.49.0,noise
rust-0.49.0,tls
that is then queried along the other ones.
The process of adding implementations can be improved later, either by creating a cli tool that does it or, getting another primary format, that is then parsed by the composer and converted to sql
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
I added some thoughts :)
{ | ||
"name": "composer", | ||
"version": "0.0.1", | ||
"description": "", | ||
"main": "index.ts", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"author": "", | ||
"license": "ISC", | ||
"devDependencies": { | ||
"@types/node": "^18.8.4", | ||
"@types/yargs": "^17.0.13", | ||
"ts-node": "^10.9.1", | ||
"typescript": "^4.8.4" | ||
}, | ||
"dependencies": { | ||
"@iarna/toml": "^2.2.5", | ||
"@types/iarna__toml": "^2.0.2", | ||
"sqlite": "^4.1.2", | ||
"sqlite3": "^5.1.2", | ||
"yargs": "^17.6.2" | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Has DENO been considered as an alternative? It would allow us to put everything in a single file without having to install dependencies etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for bringing this, yeah I considered but as it wasn't present by default on ubuntu-latest
and we weren't using container images on the workflow I didn't want to introduce it. But if we can I am happy to use it if everyone agrees.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Installing it seems to be easy enough: https://github.com/denoland/setup-deno
I think this would be a good usecase for it, should make this script a lot more maintainable.
import sqlite3 from "sqlite3"; | ||
import { open } from "sqlite"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the difference between these two packages?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Call sqlite to process the csv resource files and generate a database. | ||
// We call the sqlite process instead of doing it here cause | ||
// the dot commands are interpreted by the sqlite cli tool not sqlite itself, | ||
// and it is a lot faster parsing the csv's. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our CSVs are <10 lines long. What am I meant to take away from this comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that we can't call sqlite dot commands via the database driver, therefore we do it via execFile
therefore instead of parsing the csv
file with js, we do it with sqlite
instead cause it's faster.
Our CSVs are <10 lines long.
but they are expected to grow I assume, do you suggest importing, parsing and inserting in typescript land instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our CSVs are <10 lines long.
but they are expected to grow I assume
I am guessing they would have to grow into the thousands for performance to become a problem and thus a driving factor for the design. I hope that we won't have CSV files that are 1000s of lines long!
do you suggest importing, parsing and inserting in typescript land instead?
I think we should do whatever results in the better design. If we want to have a test for this, I think it will likely be easier if we don't need to set up dummy files for the tests but can pass data in as variables. That would suggest that we use SQL to insert the data which in turn means parsing the files in TS.
composer/index.ts
Outdated
const db = await open({ | ||
filename: DB, | ||
driver: sqlite3.Database, | ||
}); | ||
|
||
// Generate the testing combinations by SELECT'ing from both transports | ||
// and muxers tables the distinct combinations where the transport and the muxer | ||
// of the different libp2p implementations match. | ||
const queryResults = | ||
await db.all(`SELECT DISTINCT a.id as id1, b.id as id2, a.transport, ma.muxer | ||
FROM transports a, transports b, muxers ma, muxers mb | ||
WHERE a.id != b.id | ||
AND a.transport == b.transport | ||
AND a.id == ma.id | ||
AND b.id == mb.id | ||
AND ma.muxer == mb.muxer;`); | ||
await db.close(); | ||
|
||
let global = new Global( | ||
"multidimensional-testing", | ||
"multidimensional", | ||
argv.total_instances | ||
); | ||
let composition = new Composition(global, []); | ||
|
||
for (let row of queryResults) { | ||
// Instance count is hardcoded to 1 for now. | ||
let instance = new Instance(1); | ||
|
||
let build_args1 = new BuildArgs( | ||
row.transport, | ||
row.muxer, | ||
row.id1, | ||
argv.gitRef, | ||
argv.gitTarget | ||
); | ||
let build_config1 = new BuildConfig(build_args1); | ||
let group1 = new Group(row.id1, BUILDER, instance, build_config1); | ||
|
||
let build_args2 = new BuildArgs( | ||
row.transport, | ||
row.muxer, | ||
row.id2, | ||
argv.gitRef, | ||
argv.gitTarget | ||
); | ||
let build_config2 = new BuildConfig(build_args2); | ||
let group2 = new Group(row.id2, BUILDER, instance, build_config2); | ||
|
||
let run = new Run( | ||
`${row.id1} x ${row.id2} x ${row.transport} x ${row.muxer}`, | ||
[group1, group2] | ||
); | ||
|
||
composition.runs.push(run); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to have a test for this snippet of code.
- So we can make sure it works.
- To make review easier: I don't have to run this locally to see the output.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah agree, and I am planning to do it after closing the spec.
rust-master,tcp | ||
rust-master,quic | ||
rust-master,tcp | ||
rust-0.49.0,tcp | ||
rust-0.48.0,tcp | ||
rust-0.47.0,tcp | ||
go-0.23.4,tcp | ||
go-0.23.4,quic |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to get really repetitive (and error prone, see lines 2 and 4 are duplicates) as we release new versions. If we already build a tool that generates the combinations for us, wouldn't it make more sense to track a semver specifier that marks, which versions support which feature?
What we would track is:
language | quic | yamux | mplex | tcp |
---|---|---|---|---|
rust | > 0.50.0 | > 0.20.01 | ... | ... |
go | > 0.24.3 | ... | ... | ... |
A null
entry would mean unsupported.
If we ever decide to remove a feature, we can use a semver range: > 0.50.0 < 0.57.0
.
Given this table, we only need one other list for each language that specifies the versions we want to test, e.g. for Rust, that could say:
- 0.45.0
- 0.46.0
- ...
I am not sure if sqlite is still the best tool for this. We might be able to use it to generate the combinations initially but throw out the ones that don't match the semver range. There might also be a module that can do semver parsing in sqlite, I haven't checked.
In any case, I think this would be a lot more maintainable going forward.
Thoughts?
Footnotes
-
Just making this up. ↩
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this links with @p-shahi's question on #75 (comment) and your comment on #75 (comment) I think.
Yeah this seems to me an elegant solution to solve the increasing number of dimensions into csv files and I don't think it is incompatible with using sqlite
. I.e we could define the format suggested above with semver's and then transform it into the csv
"tables" and insert them into sqlite
tables for then query them.
But I'd leave this to a subsequent phase, as a improvement to the Extract part of the ETL. Wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this as well! agree with @jxs this should be a next step rather than a requirement for the MVP.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am okay with doing it in a follow-up if we think that the overall design holds.
Your reference to ETL is interesting. I hadn't considered that we can use the suggested table to then produce the current ones. I would have seen that as an unnecessary intermediate step but perhaps it is easier to implement if we do the generation in multiple steps, thus forming a pipeline.
.catch((err) => { | ||
console.error(err); | ||
process.exit(1); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(creating here just to get a thread)
pass all the test parameters (transport, muxer, protocol) when launching the container the work becomes a lot easier for the composer and we could also combine it with testground/testground#1522.
Does testground currently support passing env vars when launching containers @laurentsenta?
Yes, the idiomatic solution is to use the run parameters,
there is an example of this in the ping test:
Lines 69 to 71 in abce1ee
secureChannel = runenv.StringParam("secure_channel") | |
maxLatencyMs = runenv.IntParam("max_latency_ms") | |
iterations = runenv.IntParam("iterations") |
You'd pass the parameters in the runs
directly or in the runs.group
field:
test-plans/composer/demo/composition-example.toml
Lines 79 to 80 in 3fccfb2
[runs.test_params] | |
iterations = "5" |
.then(() => process.exit(0)) | ||
.catch((err) => { | ||
console.error(err); | ||
process.exit(1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(another thread)
Wdyt of using just docker:generic to simplify the process @laurentsenta @mxinden?
If you want to tackle this question as part of this PR:
Initially, we planned on:
- Implementing the test using testground builders + runners,
- Rely on
docker:generic
anddocker_extensions
to implement missing features, - As we converge to a reliable solution, make the features Testground natives (add a
docker:rust
builder for example, and other simplifications). - With this approach, I would NOT recommend moving to
docker:generic
, but instead moving features into testground.
It seems we're now moving towards a different design:
- Implementing the tests using [external] builders + testground's runners.
- With this approach, I would recommend investing in external builders rather than rewriting what we have.
- the first should be runtime parameters whereas version should be a build parameters - separate Go and Rust git ref and target
closing in favor of #85 |
This is an initial version of the composer tool. I am submitting this as a draft PR so we can broaden the discussion regarding the assumptions I did.
I followed the idea of using
csv
files withsqlite
from @MarcoPolo which turned great cause it allows us to model the data and create all the combinations in a much simpler way using sql.But due to the difficulty of modeling all the test and build parameters into
csv
files, including the different natures ofgo
andrust
test plans which use different builders, and after speaking with @laurentsenta and @MarcoPolo it occurred to me that if we simplify on the builder to bedocker:generic
and, pass the version as we currently do via[groups.build_config.build_args]
and pass all the test parameters (transport, muxer, protocol) when launching the container the work becomes a lot easier for the
composer
and we could also combine it with testground/testground#1522.Does testground currently support passing env vars when launching containers @laurentsenta?
While on the
Go
side we'd had to change the test plans to start usingdocker:generic
and change the way the parameters are passed, the changes required on theRust
side we'd just to rename the binary files to match theVERSION
passed on thecomposition.toml
file.Wdyt of using just
docker:generic
to simplify the process @laurentsenta @mxinden?a run of composer with these
csv
files produces the followingcomposition.toml
Thanks.