From 8e257991d80277950915a77857ea7e724001b195 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 25 Oct 2019 23:33:46 +0300 Subject: Add support for tests, examples, and benchmark package manifest values --- libbrep/package.cxx | 6 + libbrep/package.hxx | 23 +- libbrep/package.xml | 258 +++++++++++++++++++++++ load/load.cxx | 224 ++++++++++++-------- mod/mod-package-version-details.cxx | 143 ++++++++----- tests/.gitignore | 2 + tests/load/1/math/libfoo-1.2.4+1.tar.gz | Bin 993 -> 1025 bytes tests/load/1/math/libfoo-benchmarks-1.2.4.tar.gz | Bin 0 -> 262 bytes tests/load/1/math/libfoo-examples-1.2.4.tar.gz | Bin 0 -> 268 bytes tests/load/1/math/libfoo-tests-1.2.4.tar.gz | Bin 0 -> 259 bytes tests/load/1/math/packages.manifest | 29 ++- tests/load/driver.cxx | 36 ++-- www/package-version-details-body.css | 36 ++++ 13 files changed, 597 insertions(+), 160 deletions(-) create mode 100644 tests/load/1/math/libfoo-benchmarks-1.2.4.tar.gz create mode 100644 tests/load/1/math/libfoo-examples-1.2.4.tar.gz create mode 100644 tests/load/1/math/libfoo-tests-1.2.4.tar.gz diff --git a/libbrep/package.cxx b/libbrep/package.cxx index fe216d2..e6c543d 100644 --- a/libbrep/package.cxx +++ b/libbrep/package.cxx @@ -73,6 +73,9 @@ namespace brep optional bee, dependencies_type dp, requirements_type rq, + small_vector ts, + small_vector es, + small_vector bms, build_class_exprs bs, build_constraints_type bc, optional lc, @@ -104,6 +107,9 @@ namespace brep build_error_email (move (bee)), dependencies (move (dp)), requirements (move (rq)), + tests (move (ts)), + examples (move (es)), + benchmarks (move (bms)), builds (move (bs)), build_constraints (!stub () ? move (bc) : build_constraints_type ()), internal_repository (move (rp)), diff --git a/libbrep/package.hxx b/libbrep/package.hxx index 9733374..b9a7c00 100644 --- a/libbrep/package.hxx +++ b/libbrep/package.hxx @@ -21,7 +21,7 @@ // #define LIBBREP_PACKAGE_SCHEMA_VERSION_BASE 14 -#pragma db model version(LIBBREP_PACKAGE_SCHEMA_VERSION_BASE, 16, closed) +#pragma db model version(LIBBREP_PACKAGE_SCHEMA_VERSION_BASE, 17, closed) namespace brep { @@ -86,9 +86,9 @@ namespace brep // dependencies // - using bpkg::dependency_constraint; + using bpkg::version_constraint; - #pragma db value(dependency_constraint) definition + #pragma db value(version_constraint) definition // Notes: // @@ -139,7 +139,7 @@ namespace brep using package_type = brep::package; package_name name; - optional constraint; + optional constraint; // Resolved dependency package. NULL if the repository load was shallow // and so the package dependencies are not resolved. @@ -389,6 +389,9 @@ namespace brep optional build_error_email, dependencies_type, requirements_type, + small_vector tests, + small_vector examples, + small_vector benchmarks, build_class_exprs, build_constraints_type, optional location, @@ -449,6 +452,9 @@ namespace brep optional build_error_email; dependencies_type dependencies; requirements_type requirements; + small_vector tests; + small_vector examples; + small_vector benchmarks; build_class_exprs builds; // Note: foreign-mapped in build. build_constraints_type build_constraints; // Note: foreign-mapped in build. @@ -552,6 +558,15 @@ namespace brep set(odb::nested_set (this.requirements, std::move (?))) \ id_column("") key_column("") value_column("id") + // tests, examples, benchmarks + // + // Seeing that these reuse the dependency types, we are also going to + // have identical database mapping. + // + #pragma db member(tests) id_column("") value_column("dep_") + #pragma db member(examples) id_column("") value_column("dep_") + #pragma db member(benchmarks) id_column("") value_column("dep_") + // builds // #pragma db member(builds) id_column("") value_column("") \ diff --git a/libbrep/package.xml b/libbrep/package.xml index 2acba62..170ba7c 100644 --- a/libbrep/package.xml +++ b/libbrep/package.xml @@ -1,4 +1,262 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/load/load.cxx b/load/load.cxx index c786551..83cc9e6 100644 --- a/load/load.cxx +++ b/load/load.cxx @@ -391,11 +391,12 @@ load_packages (const shared_ptr& rp, // that we expect dependency constraints to be complete. // for (manifest_name_value nv (mp.next ()); !nv.empty (); nv = mp.next ()) - pms.emplace_back (mp, - move (nv), - ignore_unknown, - false /* complete_depends */, - package_manifest_flags::forbid_incomplete_depends); + pms.emplace_back ( + mp, + move (nv), + ignore_unknown, + false /* complete_depends */, + package_manifest_flags::forbid_incomplete_dependencies); } else pms = pkg_package_manifests (mp, ignore_unknown); @@ -406,6 +407,8 @@ load_packages (const shared_ptr& rp, throw failed (); } + using brep::dependency; + for (package_manifest& pm: pms) { shared_ptr p ( @@ -501,11 +504,28 @@ load_packages (const shared_ptr& rp, // The package member will be assigned during dependency // resolution procedure. // - ds.back ().push_back ({move (pd.name), - move (pd.constraint), - nullptr /* package */}); + ds.back ().push_back (dependency {move (pd.name), + move (pd.constraint), + nullptr /* package */}); } + auto deps = [] (small_vector&& ds) + { + small_vector r; + + if (!ds.empty ()) + { + r.reserve (ds.size ()); + + for (bpkg::dependency& d: ds) + r.push_back (dependency {move (d.name), + move (d.constraint), + nullptr /* package */}); + } + + return r; + }; + // Cache before the package name is moved. // package_name project (pm.effective_project ()); @@ -534,6 +554,9 @@ load_packages (const shared_ptr& rp, move (pm.build_error_email), move (ds), move (pm.requirements), + deps (move (pm.tests)), + deps (move (pm.examples)), + deps (move (pm.benchmarks)), move (pm.builds), move (pm.build_constraints), move (pm.location), @@ -827,110 +850,143 @@ find (const lazy_shared_ptr& r, return false; } -// Resolve package dependencies. Make sure that the best matching dependency -// belongs to the package repositories, their immediate prerequisite -// repositories, or their complements, recursively. Should be called once per -// internal package. +// Resolve package run-time dependencies, tests, examples, and benchmarks. +// Make sure that the best matching dependency belongs to the package +// repositories, their complements, recursively, or their immediate +// prerequisite repositories (only for run-time dependencies). Should be +// called once per internal package. // static void resolve_dependencies (package& p, database& db) { + using brep::dependency; + using brep::dependency_alternatives; + // Resolve dependencies for internal packages only. // assert (p.internal ()); - if (p.dependencies.empty ()) + if (p.dependencies.empty () && + p.tests.empty () && + p.examples.empty () && + p.benchmarks.empty ()) return; - for (auto& da: p.dependencies) + auto resolve = [&p, &db] (dependency& d, bool prereq) { - for (auto& d: da) - { - // Dependency should not be resolved yet. - // - assert (d.package == nullptr); + // Dependency should not be resolved yet. + // + assert (d.package == nullptr); - using query = query; - query q (query::id.name == d.name); - const auto& vm (query::id.version); + using query = query; + query q (query::id.name == d.name); + const auto& vm (query::id.version); - if (d.constraint) - { - auto c (*d.constraint); + if (d.constraint) + { + const version_constraint& c (*d.constraint); - assert (c.complete ()); + assert (c.complete ()); - query qs (compare_version_eq (vm, - canonical_version (wildcard_version), - false /* revision */)); + query qs (compare_version_eq (vm, + canonical_version (wildcard_version), + false /* revision */)); - if (c.min_version && c.max_version && - *c.min_version == *c.max_version) + if (c.min_version && c.max_version && *c.min_version == *c.max_version) + { + const version& v (*c.min_version); + q = q && (compare_version_eq (vm, + canonical_version (v), + v.revision.has_value ()) || + qs); + } + else + { + query qr (true); + + if (c.min_version) { const version& v (*c.min_version); - q = q && - (compare_version_eq (vm, - canonical_version (v), - v.revision.has_value ()) || - qs); - } - else - { - query qr (true); + canonical_version cv (v); + bool rv (v.revision); - if (c.min_version) - { - const version& v (*c.min_version); - canonical_version cv (v); - bool rv (v.revision); - - if (c.min_open) - qr = compare_version_gt (vm, cv, rv); - else - qr = compare_version_ge (vm, cv, rv); - } - - if (c.max_version) - { - const version& v (*c.max_version); - canonical_version cv (v); - bool rv (v.revision); - - if (c.max_open) - qr = qr && compare_version_lt (vm, cv, rv); - else - qr = qr && compare_version_le (vm, cv, rv); - } - - q = q && (qr || qs); + if (c.min_open) + qr = compare_version_gt (vm, cv, rv); + else + qr = compare_version_ge (vm, cv, rv); } - } - for (const auto& pp: db.query (q + order_by_version_desc (vm))) - { - if (find (p.internal_repository, pp)) + if (c.max_version) { - d.package.reset (db, pp.id); - break; + const version& v (*c.max_version); + canonical_version cv (v); + bool rv (v.revision); + + if (c.max_open) + qr = qr && compare_version_lt (vm, cv, rv); + else + qr = qr && compare_version_le (vm, cv, rv); } + + q = q && (qr || qs); } + } - if (d.package == nullptr) + for (const auto& pp: db.query (q + order_by_version_desc (vm))) + { + if (find (p.internal_repository, pp, prereq)) { - cerr << "error: can't resolve dependency " << d << " of the package " - << p.name << " " << p.version << endl - << " info: repository " - << p.internal_repository.load ()->location - << " appears to be broken" << endl; - - // Practically it is enough to resolve at least one dependency - // alternative to build a package. Meanwhile here we consider an error - // specifying in the manifest file an alternative which can't be - // resolved. - // - throw failed (); + d.package.reset (db, pp.id); + return true; } } + + return false; + }; + + auto bail = [&p] (const dependency& d, const char* what) + { + cerr << "error: can't resolve " << what << " " << d << " for the package " + << p.name << " " << p.version << endl + << " info: repository " << p.internal_repository.load ()->location + << " appears to be broken" << endl; + + throw failed (); + }; + + for (dependency_alternatives& da: p.dependencies) + { + for (dependency& d: da) + { + // Practically it is enough to resolve at least one dependency + // alternative to build a package. Meanwhile here we consider an error + // specifying in the manifest file an alternative which can't be + // resolved. + // + if (!resolve (d, true /* prereq */)) + bail (d, "dependency"); + } + } + + // Should we allow tests, examples, and benchmarks packages to be + // unresolvable? Let's forbid that until we see a use case for that. + // + for (dependency& d: p.tests) + { + if (!resolve (d, false /* prereq */)) + bail (d, "tests"); + } + + for (dependency& d: p.examples) + { + if (!resolve (d, false /* prereq */)) + bail (d, "examples"); + } + + for (dependency& d: p.benchmarks) + { + if (!resolve (d, false /* prereq */)) + bail (d, "benchmarks"); } db.update (p); // Update the package state. diff --git a/mod/mod-package-version-details.cxx b/mod/mod-package-version-details.cxx index b22e091..cc89048 100644 --- a/mod/mod-package-version-details.cxx +++ b/mod/mod-package-version-details.cxx @@ -267,6 +267,53 @@ handle (request& rq, response& rs) << ~TBODY << ~TABLE; + auto print_dependency = [&s, &root, this] (const dependency& d) + { + const auto& dcon (d.constraint); + const package_name& dname (d.name); + + // Try to display the dependency as a link if it is resolved. + // Otherwise display it as a plain text. + // + if (d.package != nullptr) + { + shared_ptr p (d.package.load ()); + assert (p->internal () || !p->other_repositories.empty ()); + + shared_ptr r (p->internal () + ? p->internal_repository.load () + : p->other_repositories[0].load ()); + + string ename (mime_url_encode (dname.string (), false)); + + if (r->interface_url) + { + string u (*r->interface_url + ename); + s << A(HREF=u) << dname << ~A; + + if (dcon) + s << ' ' + << A(HREF=u + "/" + p->version.string ()) << *dcon << ~A; + } + else if (p->internal ()) + { + dir_path u (tenant_dir (root, tenant) / dir_path (ename)); + s << A(HREF=u) << dname << ~A; + + if (dcon) + s << ' ' + << A(HREF=u / path (p->version.string ())) << *dcon << ~A; + } + else + // Display the dependency as a plain text if no repository URL + // available. + // + s << d; + } + else + s << d; + }; + const auto& ds (pkg->dependencies); if (!ds.empty ()) { @@ -294,50 +341,7 @@ handle (request& rq, response& rs) if (&d != &da[0]) s << " | "; - const auto& dcon (d.constraint); - const package_name& dname (d.name); - - // Try to display the dependency as a link if it is resolved. - // Otherwise display it as a plain text. - // - if (d.package != nullptr) - { - shared_ptr p (d.package.load ()); - assert (p->internal () || !p->other_repositories.empty ()); - - shared_ptr r ( - p->internal () - ? p->internal_repository.load () - : p->other_repositories[0].load ()); - - string ename (mime_url_encode (dname.string (), false)); - - if (r->interface_url) - { - string u (*r->interface_url + ename); - s << A(HREF=u) << dname << ~A; - - if (dcon) - s << ' ' - << A(HREF=u + "/" + p->version.string ()) << *dcon << ~A; - } - else if (p->internal ()) - { - dir_path u (tenant_dir (root, tenant) / dir_path (ename)); - s << A(HREF=u) << dname << ~A; - - if (dcon) - s << ' ' - << A(HREF=u / path (p->version.string ())) << *dcon << ~A; - } - else - // Display the dependency as a plain text if no repository URL - // available. - // - s << d; - } - else - s << d; + print_dependency (d); } s << ~SPAN @@ -350,15 +354,6 @@ handle (request& rq, response& rs) << ~TABLE; } - bool builds (build_db_ != nullptr && pkg->buildable); - - if (builds) - package_db_->load (*pkg, pkg->build_section); - - bool archived (package_db_->load (tenant)->archived); - - t.commit (); - const auto& rm (pkg->requirements); if (!rm.empty ()) { @@ -402,6 +397,48 @@ handle (request& rq, response& rs) << ~TABLE; } + auto print_dependencies = [&s, &print_dependency] + (const small_vector& deps, + const char* heading, + const char* id) + { + if (!deps.empty ()) + { + s << H3 << heading << ~H3 + << TABLE(CLASS="proplist", ID=id) + << TBODY; + + for (const dependency& d: deps) + { + s << TR(CLASS=id) + << TD + << SPAN(CLASS="value"); + + print_dependency (d); + + s << ~SPAN + << ~TD + << ~TR; + } + + s << ~TBODY + << ~TABLE; + } + }; + + print_dependencies (pkg->tests, "Tests", "tests"); + print_dependencies (pkg->examples, "Examples", "examples"); + print_dependencies (pkg->benchmarks, "Benchmarks", "benchmarks"); + + bool builds (build_db_ != nullptr && pkg->buildable); + + if (builds) + package_db_->load (*pkg, pkg->build_section); + + bool archived (package_db_->load (tenant)->archived); + + t.commit (); + if (builds) { using bbot::build_config; diff --git a/tests/.gitignore b/tests/.gitignore index e54525b..2e508a9 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1 +1,3 @@ driver +test/ +test-*/ diff --git a/tests/load/1/math/libfoo-1.2.4+1.tar.gz b/tests/load/1/math/libfoo-1.2.4+1.tar.gz index 5d19fa6..74678eb 100644 Binary files a/tests/load/1/math/libfoo-1.2.4+1.tar.gz and b/tests/load/1/math/libfoo-1.2.4+1.tar.gz differ diff --git a/tests/load/1/math/libfoo-benchmarks-1.2.4.tar.gz b/tests/load/1/math/libfoo-benchmarks-1.2.4.tar.gz new file mode 100644 index 0000000..606893a Binary files /dev/null and b/tests/load/1/math/libfoo-benchmarks-1.2.4.tar.gz differ diff --git a/tests/load/1/math/libfoo-examples-1.2.4.tar.gz b/tests/load/1/math/libfoo-examples-1.2.4.tar.gz new file mode 100644 index 0000000..c1d5fbd Binary files /dev/null and b/tests/load/1/math/libfoo-examples-1.2.4.tar.gz differ diff --git a/tests/load/1/math/libfoo-tests-1.2.4.tar.gz b/tests/load/1/math/libfoo-tests-1.2.4.tar.gz new file mode 100644 index 0000000..8e5105f Binary files /dev/null and b/tests/load/1/math/libfoo-tests-1.2.4.tar.gz differ diff --git a/tests/load/1/math/packages.manifest b/tests/load/1/math/packages.manifest index 429e61f..de3b1c5 100644 --- a/tests/load/1/math/packages.manifest +++ b/tests/load/1/math/packages.manifest @@ -79,8 +79,35 @@ requires: linux | windows | macosx; Symbian support is coming. requires: c++11 requires: ? ; libc++ standard library if using Clang on Mac OS X. requires: ? vc++ >= 12.0; Only if using VC++ on Windows. +tests: libfoo-tests == 1.2.4 +examples: libfoo-examples +benchmarks: libfoo-benchmarks > 0.0.1 location: libfoo-1.2.4+1.tar.gz -sha256sum: 533108c89724a80ba739168ec92540dff0b7d3660fa0771de780d8595ccff425 +sha256sum: c02b6033107387e05f48aa62ee6498152c967deb0e91a62f1e618fe9fd1bc644 +: +name: libfoo-benchmarks +version: 1.2.4 +summary: The Foo Math Library benchmarks +license: MIT +builds: none; Is only build to benchmark libfoo. +location: libfoo-benchmarks-1.2.4.tar.gz +sha256sum: 2ec3985a540ca5bf74786d0792820cfa8a2790964a5aeaba443dfa91f2a54c04 +: +name: libfoo-examples +version: 1.2.4 +summary: The Foo Math Library examples +license: MIT +builds: none; Is only built to demo libfoo usage. +location: libfoo-examples-1.2.4.tar.gz +sha256sum: 99658b9a5a5b834047b692b93ded9f9af3d255eb5ea3b27594f600b902039995 +: +name: libfoo-tests +version: 1.2.4 +summary: The Foo Math Library tests +license: MIT +builds: none; Is only built to test libfoo. +location: libfoo-tests-1.2.4.tar.gz +sha256sum: 16712c90df5ba2ffb920d29c9c25a29564f8ae01f167359c4651572789e6cd6c : name: libpq version: 0 diff --git a/tests/load/driver.cxx b/tests/load/driver.cxx index 6877f4b..d685c18 100644 --- a/tests/load/driver.cxx +++ b/tests/load/driver.cxx @@ -203,7 +203,7 @@ main (int argc, char* argv[]) } static inline dependency -dep (const char* n, optional c) +dep (const char* n, optional c) { return dependency {package_name (n), move (c), nullptr}; } @@ -270,7 +270,7 @@ test_git_repos (const cstrings& loader_args, assert (p->dependencies[0][0] == dep ("libmisc", - dependency_constraint ( + version_constraint ( dep_ver ("1.0"), false, dep_ver ("1.0"), false))); assert (p->buildable); @@ -311,7 +311,7 @@ test_pkg_repos (const cstrings& loader_args, query::id.tenant == tenant).size () == 7); assert (db.query ( - query::id.tenant == tenant).size () == 18); + query::id.tenant == tenant).size () == 21); shared_ptr sr ( db.load (repository_id (tenant, @@ -466,12 +466,12 @@ test_pkg_repos (const cstrings& loader_args, assert (fpv2->dependencies[0][0] == dep ("libbar", - dependency_constraint ( + version_constraint ( nullopt, true, dep_ver ("2.4.0"), false))); assert (fpv2->dependencies[1][0] == dep ("libexp", - dependency_constraint ( + version_constraint ( dep_ver ("+2-1.2"), false, dep_ver ("+2-1.2"), false))); assert (check_location (fpv2)); @@ -513,27 +513,27 @@ test_pkg_repos (const cstrings& loader_args, assert (fpv2a->dependencies[0][0] == dep ("libmisc", - dependency_constraint ( + version_constraint ( dep_ver ("0.1"), false, dep_ver ("2.0.0-"), true))); assert (fpv2a->dependencies[0][1] == dep ("libmisc", - dependency_constraint ( + version_constraint ( dep_ver ("2.0"), false, dep_ver ("5.0"), false))); assert (fpv2a->dependencies[1][0] == dep ("libgenx", - dependency_constraint ( + version_constraint ( dep_ver ("0.2"), true, dep_ver ("3.0"), true))); assert (fpv2a->dependencies[2][0] == dep ("libexpat", - dependency_constraint ( + version_constraint ( nullopt, true, dep_ver ("5.2"), true))); assert (fpv2a->dependencies[2][1] == dep ("libexpat", - dependency_constraint ( + version_constraint ( dep_ver ("1"), true, dep_ver ("5.1"), false))); assert (fpv2a->requirements.empty ()); @@ -573,7 +573,7 @@ test_pkg_repos (const cstrings& loader_args, assert (fpv3->dependencies[0].size () == 1); assert (fpv3->dependencies[0][0] == dep ("libmisc", - dependency_constraint ( + version_constraint ( dep_ver ("2.0.0"), false, nullopt, true))); assert (check_location (fpv3)); @@ -612,7 +612,7 @@ test_pkg_repos (const cstrings& loader_args, assert (fpv4->dependencies[0].size () == 1); assert (fpv4->dependencies[0][0] == dep ("libmisc", - dependency_constraint ( + version_constraint ( dep_ver ("2.0.0"), false, nullopt, true))); assert (check_location (fpv4)); @@ -696,7 +696,7 @@ test_pkg_repos (const cstrings& loader_args, assert (xpv->dependencies[0].size () == 1); assert (xpv->dependencies[0][0] == dep ("libexpat", - dependency_constraint ( + version_constraint ( dep_ver ("2.0.0"), false, nullopt, true))); assert (xpv->dependencies[1].size () == 1); @@ -781,12 +781,12 @@ test_pkg_repos (const cstrings& loader_args, assert (fpv5->dependencies[0][0] == dep ("libmisc", - dependency_constraint ( + version_constraint ( nullopt, true, dep_ver ("1.1"), true))); assert (fpv5->dependencies[0][1] == dep ("libmisc", - dependency_constraint ( + version_constraint ( dep_ver ("2.3.0+0"), true, nullopt, true))); assert (fpv5->dependencies[1].size () == 1); @@ -794,7 +794,7 @@ test_pkg_repos (const cstrings& loader_args, assert (fpv5->dependencies[1][0] == dep ("libexp", - dependency_constraint ( + version_constraint ( dep_ver ("1.0"), false, nullopt, true))); assert (fpv5->dependencies[2].size () == 2); @@ -826,7 +826,7 @@ test_pkg_repos (const cstrings& loader_args, assert (check_location (fpv5)); assert (fpv5->sha256sum && *fpv5->sha256sum == - "533108c89724a80ba739168ec92540dff0b7d3660fa0771de780d8595ccff425"); + "c02b6033107387e05f48aa62ee6498152c967deb0e91a62f1e618fe9fd1bc644"); assert (fpv5->buildable); @@ -866,7 +866,7 @@ test_pkg_repos (const cstrings& loader_args, assert (epv->dependencies[1].size () == 1); assert (epv->dependencies[1][0] == dep ("libpq", - dependency_constraint ( + version_constraint ( dep_ver ("9.0.0"), false, nullopt, true))); assert (epv->requirements.empty ()); diff --git a/www/package-version-details-body.css b/www/package-version-details-body.css index 62937c1..772f9eb 100644 --- a/www/package-version-details-body.css +++ b/www/package-version-details-body.css @@ -244,6 +244,42 @@ h1, h2, h3 font-size: 0.94em; } +#tests {margin-top: .4em; margin-bottom: 1em;} + +#tests tr:nth-child(even) td {background-color: rgba(0, 0, 0, 0.07);} +#tests td {margin-left: 2.8em; padding-left: .4em;} + +#tests tr.tests td .value +{ + /* style. */ + font-family: monospace; + font-size: 0.94em; +} + +#examples {margin-top: .4em; margin-bottom: 1em;} + +#examples tr:nth-child(even) td {background-color: rgba(0, 0, 0, 0.07);} +#examples td {margin-left: 2.8em; padding-left: .4em;} + +#examples tr.examples td .value +{ + /* style. */ + font-family: monospace; + font-size: 0.94em; +} + +#benchmarks {margin-top: .4em; margin-bottom: 1em;} + +#benchmarks tr:nth-child(even) td {background-color: rgba(0, 0, 0, 0.07);} +#benchmarks td {margin-left: 2.8em; padding-left: .4em;} + +#benchmarks tr.benchmarks td .value +{ + /* style. */ + font-family: monospace; + font-size: 0.94em; +} + /* * Builds. */ -- cgit v1.1