From 22d73c9ded10d8164c89656f766e233572da35d5 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Wed, 15 Feb 2023 11:53:28 -0600 Subject: [PATCH] Move tests to a separate package; update GitHub CI and docs --- .github/workflows/lint.yml | 4 +- .github/workflows/test.yml | 14 ++- deps/formatter/Project.toml | 5 - deps/formatter/format.jl | 8 -- docs/src/usage.md | 6 -- juliaw | 75 -------------- mkdocs.yml | 23 ----- test/Project.toml | 19 ++++ {instances => test/fixtures}/s1.json | 0 test/fixtures/s1.zip | Bin 0 -> 1089 bytes {instances => test/fixtures}/s2.json | 0 .../fixtures}/solutions/s1.json | 0 {instances => test/fixtures}/solutions/s1.log | 0 test/graph/build_test.jl | 39 -------- test/graph/dist_test.jl | 25 ----- test/instance/compress_test.jl | 53 ---------- test/instance/geodb_test.jl | 25 ----- test/instance/parse_test.jl | 93 ------------------ test/model/build_test.jl | 38 ------- test/model/resolve_test.jl | 13 --- test/model/solve_test.jl | 70 ------------- test/reports_test.jl | 21 ---- test/runtests.jl | 22 ----- test/src/RELOGT.jl | 51 ++++++++++ test/src/graph/build_test.jl | 40 ++++++++ test/src/graph/dist_test.jl | 27 +++++ test/src/instance/compress_test.jl | 54 ++++++++++ test/src/instance/geodb_test.jl | 27 +++++ test/src/instance/parse_test.jl | 87 ++++++++++++++++ test/src/model/build_test.jl | 40 ++++++++ test/src/model/resolve_test.jl | 13 +++ test/src/model/solve_test.jl | 70 +++++++++++++ test/src/reports_test.jl | 21 ++++ 33 files changed, 463 insertions(+), 520 deletions(-) delete mode 100644 deps/formatter/Project.toml delete mode 100644 deps/formatter/format.jl delete mode 100755 juliaw delete mode 100644 mkdocs.yml create mode 100644 test/Project.toml rename {instances => test/fixtures}/s1.json (100%) create mode 100644 test/fixtures/s1.zip rename {instances => test/fixtures}/s2.json (100%) rename {instances => test/fixtures}/solutions/s1.json (100%) rename {instances => test/fixtures}/solutions/s1.log (100%) delete mode 100644 test/graph/build_test.jl delete mode 100644 test/graph/dist_test.jl delete mode 100644 test/instance/compress_test.jl delete mode 100644 test/instance/geodb_test.jl delete mode 100644 test/instance/parse_test.jl delete mode 100644 test/model/build_test.jl delete mode 100644 test/model/resolve_test.jl delete mode 100644 test/model/solve_test.jl delete mode 100644 test/reports_test.jl delete mode 100644 test/runtests.jl create mode 100644 test/src/RELOGT.jl create mode 100644 test/src/graph/build_test.jl create mode 100644 test/src/graph/dist_test.jl create mode 100644 test/src/instance/compress_test.jl create mode 100644 test/src/instance/geodb_test.jl create mode 100644 test/src/instance/parse_test.jl create mode 100644 test/src/model/build_test.jl create mode 100644 test/src/model/resolve_test.jl create mode 100644 test/src/model/solve_test.jl create mode 100644 test/src/reports_test.jl diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b71acf6..327c0ef 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -14,10 +14,10 @@ jobs: shell: julia --color=yes {0} run: | using Pkg - Pkg.add(PackageSpec(name="JuliaFormatter", version="0.14.4")) + Pkg.add(PackageSpec(name="JuliaFormatter", version="1")) using JuliaFormatter format("src", verbose=true) - format("test", verbose=true) + format("test/src", verbose=true) out = String(read(Cmd(`git diff`))) if isempty(out) exit(0) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5aa8f86..e2c31cf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,5 +21,15 @@ jobs: with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - - uses: julia-actions/julia-buildpkg@v1 - - uses: julia-actions/julia-runtest@v1 + - name: Run tests + shell: julia --color=yes --project=test {0} + run: | + using Pkg + Pkg.develop(path=".") + Pkg.update() + using RELOGT + try + runtests() + catch + exit(1) + end diff --git a/deps/formatter/Project.toml b/deps/formatter/Project.toml deleted file mode 100644 index 4bc5f25..0000000 --- a/deps/formatter/Project.toml +++ /dev/null @@ -1,5 +0,0 @@ -[deps] -JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899" - -[compat] -JuliaFormatter = "0.14.4" diff --git a/deps/formatter/format.jl b/deps/formatter/format.jl deleted file mode 100644 index 9f9d965..0000000 --- a/deps/formatter/format.jl +++ /dev/null @@ -1,8 +0,0 @@ -using JuliaFormatter -format( - [ - "../../src", - "../../test", - ], - verbose=true, -) diff --git a/docs/src/usage.md b/docs/src/usage.md index 7a2fe25..0a05396 100644 --- a/docs/src/usage.md +++ b/docs/src/usage.md @@ -10,12 +10,6 @@ using Pkg Pkg.add(name="RELOG", version="0.6") ``` -After the package and all its dependencies have been installed, please run the RELOG test suite, as shown below, to make sure that the package has been correctly installed: - -```julia -Pkg.test("RELOG") -``` - ## 2. Modeling the problem The two main model components in RELOG are **products** and **plants**. diff --git a/juliaw b/juliaw deleted file mode 100755 index b78bc72..0000000 --- a/juliaw +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/bash -# UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment -# Copyright (C) 2020-2021, UChicago Argonne, LLC. All rights reserved. -# Released under the modified BSD license. See COPYING.md for more details. - -if [ ! -e Project.toml ]; then - echo "juliaw: Project.toml not found" - exit 1 -fi - -if [ ! -e Manifest.toml ]; then - julia --project=. -e 'using Pkg; Pkg.instantiate()' || exit 1 -fi - -if [ ! -e build/sysimage.so -o Project.toml -nt build/sysimage.so ]; then - echo "juliaw: rebuilding system image..." - - # Generate temporary project folder - rm -rf $HOME/.juliaw - mkdir -p $HOME/.juliaw/src - cp Project.toml Manifest.toml $HOME/.juliaw - NAME=$(julia -e 'using TOML; toml = TOML.parsefile("Project.toml"); "name" in keys(toml) && print(toml["name"])') - if [ ! -z $NAME ]; then - cat > $HOME/.juliaw/src/$NAME.jl << EOF -module $NAME -end -EOF - fi - - # Add PackageCompiler dependencies to temporary project - julia --project=$HOME/.juliaw -e 'using Pkg; Pkg.add(["PackageCompiler", "TOML", "Logging"])' - - # Generate system image scripts - cat > $HOME/.juliaw/sysimage.jl << EOF -using PackageCompiler -using TOML -using Logging - -Logging.disable_logging(Logging.Info) -mkpath("$PWD/build") - -println("juliaw: generating precompilation statements...") -run(\`julia --project="$PWD" --trace-compile="$PWD"/build/precompile.jl \$(ARGS)\`) - -println("juliaw: finding dependencies...") -project = TOML.parsefile("Project.toml") -manifest = TOML.parsefile("Manifest.toml") -deps = Symbol[] -for dep in keys(project["deps"]) - if dep in keys(manifest) - # Up to Julia 1.6 - dep_entry = manifest[dep][1] - else - # Julia 1.7+ - dep_entry = manifest["deps"][dep][1] - end - if "path" in keys(dep_entry) - println(" - \$(dep) [skip]") - else - println(" - \$(dep)") - push!(deps, Symbol(dep)) - end -end - -println("juliaw: building system image...") -create_sysimage( - deps, - precompile_statements_file = "$PWD/build/precompile.jl", - sysimage_path = "$PWD/build/sysimage.so", -) -EOF - julia --project=$HOME/.juliaw $HOME/.juliaw/sysimage.jl $* -else - julia --project=. --sysimage build/sysimage.so $* -fi diff --git a/mkdocs.yml b/mkdocs.yml deleted file mode 100644 index 551535f..0000000 --- a/mkdocs.yml +++ /dev/null @@ -1,23 +0,0 @@ -site_name: RELOG -theme: cinder -copyright: "Copyright © 2020, UChicago Argonne, LLC. All Rights Reserved." -repo_url: https://github.com/ANL-CEEESA/RELOG -edit_uri: edit/master/src/docs/ -nav: - - Home: index.md - - Usage: usage.md - - Data Format: format.md - - Reports: reports.md - - Optimization Model: model.md -plugins: - - search -markdown_extensions: - - admonition - - mdx_math -extra_javascript: - - https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML - - js/mathjax.js -docs_dir: src/docs -site_dir: docs -extra_css: - - "css/custom.css" diff --git a/test/Project.toml b/test/Project.toml new file mode 100644 index 0000000..bcf66c4 --- /dev/null +++ b/test/Project.toml @@ -0,0 +1,19 @@ +name = "RELOGT" +uuid = "a6dae211-05d8-42ed-9081-b88c982fc90a" +authors = ["Alinson S. Xavier "] +version = "0.1.0" + +[deps] +Cbc = "9961bab8-2fa3-5c5a-9d89-47fab24efd76" +GZip = "92fee26a-97fe-5a0c-ad85-20a5f3185b63" +JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +JuMP = "4076af6c-e467-56ae-b986-b466b2749572" +JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899" +MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" +Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" +RELOG = "a2afcdf7-cf04-4913-85f9-c0d81ddf2008" +Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[compat] +JuliaFormatter = "1" \ No newline at end of file diff --git a/instances/s1.json b/test/fixtures/s1.json similarity index 100% rename from instances/s1.json rename to test/fixtures/s1.json diff --git a/test/fixtures/s1.zip b/test/fixtures/s1.zip new file mode 100644 index 0000000000000000000000000000000000000000..2d09afb79d024c323b67281c6be4b5e46c813d65 GIT binary patch literal 1089 zcmWIWW@Zs#-~d8>PxD{~D7YfSz`)L+z))wl2$GSGQ)}Dx1@nZhaAN z;(RK1>CriBE4#Cok_!8mna6TZxyq(tYg(szI_R&)#gP8InVHVl58tm(;&oc5t}v%0 z%^*v@*{%0SRPTn})2>~!uE}zqGIPz62&Iju%p;F4|1J4zU+tg#mDj>@pJ~oIciDCC z1dhpe9*bwCbBD(^FE5-@R{V&4M!THRr*-Bz*~PrSy$@tEIrvSMP}e%%Q{wWDdBSnV zBhM8XtQPaAPi*fgX^~@CV9fQ=ie=Y%$z`1&fpd%(YS|j*@o0ZvSnRc7{kKgM`z|;$ zlyG^@5MZ+H(BQkOXL?DnishpfqeFi!!xxQbGXnV~Uvk*CIXq{0aqxqc?gh_|mA96; zSvmPDY!#ejAT!CJ)F#=#-L#Cwk8{ZZhcZq1xMiu+e<`k$-aJw4jrh0a&8EI~-=(K$ zXB$p=kZ^C>-MZfeY0hgFI`{D3cz3-#{dQoowbhopY31G*pDIqy=H5Q}W>xUY>!u%H zUszWYyz;+X(dgDcOB8>)mL-$e)^An)~!F?_0RKY<x#KuST8E zRM~eg;a~lp{W-oYMe42vEH9OEG`Nqud^KJ1ZM$Ck%k0w&%i~p>^QPK_?ocRiT&A(( z*%`y!f=eGRdM-X(tTwY`>%%Dq)2GaS%vb-)?)4x=78V0sBf>=c6@&IpEHjr{g OAPfc4*MOEWFaQ7*0NhUi literal 0 HcmV?d00001 diff --git a/instances/s2.json b/test/fixtures/s2.json similarity index 100% rename from instances/s2.json rename to test/fixtures/s2.json diff --git a/instances/solutions/s1.json b/test/fixtures/solutions/s1.json similarity index 100% rename from instances/solutions/s1.json rename to test/fixtures/solutions/s1.json diff --git a/instances/solutions/s1.log b/test/fixtures/solutions/s1.log similarity index 100% rename from instances/solutions/s1.log rename to test/fixtures/solutions/s1.log diff --git a/test/graph/build_test.jl b/test/graph/build_test.jl deleted file mode 100644 index 9df3cab..0000000 --- a/test/graph/build_test.jl +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (C) 2020 Argonne National Laboratory -# Written by Alinson Santos Xavier - -using RELOG - -@testset "build_graph" begin - basedir = dirname(@__FILE__) - instance = RELOG.parsefile("$basedir/../../instances/s1.json") - graph = RELOG.build_graph(instance) - process_node_by_location_name = - Dict(n.location.location_name => n for n in graph.process_nodes) - - @test length(graph.plant_shipping_nodes) == 8 - @test length(graph.collection_shipping_nodes) == 10 - @test length(graph.process_nodes) == 6 - - node = graph.collection_shipping_nodes[1] - @test node.location.name == "C1" - @test length(node.incoming_arcs) == 0 - @test length(node.outgoing_arcs) == 2 - @test node.outgoing_arcs[1].source.location.name == "C1" - @test node.outgoing_arcs[1].dest.location.plant_name == "F1" - @test node.outgoing_arcs[1].dest.location.location_name == "L1" - @test node.outgoing_arcs[1].values["distance"] == 1695.364 - - node = process_node_by_location_name["L1"] - @test node.location.plant_name == "F1" - @test node.location.location_name == "L1" - @test length(node.incoming_arcs) == 10 - @test length(node.outgoing_arcs) == 2 - - node = process_node_by_location_name["L3"] - @test node.location.plant_name == "F2" - @test node.location.location_name == "L3" - @test length(node.incoming_arcs) == 2 - @test length(node.outgoing_arcs) == 2 - - @test length(graph.arcs) == 38 -end diff --git a/test/graph/dist_test.jl b/test/graph/dist_test.jl deleted file mode 100644 index d643602..0000000 --- a/test/graph/dist_test.jl +++ /dev/null @@ -1,25 +0,0 @@ -# RELOG: Reverse Logistics Optimization -# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. -# Released under the modified BSD license. See COPYING.md for more details. - -using RELOG - -@testset "KnnDrivingDistance" begin - # Euclidean distance between Chicago and Indianapolis - @test RELOG._calculate_distance( - 41.866, - -87.656, - 39.764, - -86.148, - RELOG.EuclideanDistance(), - ) == 265.818 - - # Approximate driving distance between Chicago and Indianapolis - @test RELOG._calculate_distance( - 41.866, - -87.656, - 39.764, - -86.148, - RELOG.KnnDrivingDistance(), - ) == 316.43 -end diff --git a/test/instance/compress_test.jl b/test/instance/compress_test.jl deleted file mode 100644 index 87d2a98..0000000 --- a/test/instance/compress_test.jl +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (C) 2020 Argonne National Laboratory -# Written by Alinson Santos Xavier - -using RELOG - -@testset "compress" begin - basedir = dirname(@__FILE__) - instance = RELOG.parsefile("$basedir/../../instances/s1.json") - compressed = RELOG._compress(instance) - - product_name_to_product = Dict(p.name => p for p in compressed.products) - location_name_to_facility = Dict() - for p in compressed.plants - location_name_to_facility[p.location_name] = p - end - for c in compressed.collection_centers - location_name_to_facility[c.name] = c - end - - p1 = product_name_to_product["P1"] - p2 = product_name_to_product["P2"] - p3 = product_name_to_product["P3"] - c1 = location_name_to_facility["C1"] - l1 = location_name_to_facility["L1"] - - @test compressed.time == 1 - @test compressed.building_period == [1] - - @test p1.name == "P1" - @test p1.transportation_cost ≈ [0.015] - @test p1.transportation_energy ≈ [0.115] - @test p1.transportation_emissions["CO2"] ≈ [0.051] - @test p1.transportation_emissions["CH4"] ≈ [0.0025] - - @test c1.name == "C1" - @test c1.amount ≈ [1869.12] - - @test l1.plant_name == "F1" - @test l1.location_name == "L1" - @test l1.energy ≈ [0.115] - @test l1.emissions["CO2"] ≈ [0.051] - @test l1.emissions["CH4"] ≈ [0.0025] - @test l1.sizes[1].opening_cost ≈ [500] - @test l1.sizes[2].opening_cost ≈ [1250] - @test l1.sizes[1].fixed_operating_cost ≈ [60] - @test l1.sizes[2].fixed_operating_cost ≈ [60] - @test l1.sizes[1].variable_operating_cost ≈ [30] - @test l1.sizes[2].variable_operating_cost ≈ [30] - @test l1.disposal_limit[p2] ≈ [2.0] - @test l1.disposal_limit[p3] ≈ [2.0] - @test l1.disposal_cost[p2] ≈ [-10.0] - @test l1.disposal_cost[p3] ≈ [-10.0] -end diff --git a/test/instance/geodb_test.jl b/test/instance/geodb_test.jl deleted file mode 100644 index e0009f0..0000000 --- a/test/instance/geodb_test.jl +++ /dev/null @@ -1,25 +0,0 @@ -# RELOG: Reverse Logistics Optimization -# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. -# Released under the modified BSD license. See COPYING.md for more details. - -using RELOG - -@testset "geodb_query (2018-us-county)" begin - region = RELOG.geodb_query("2018-us-county:17043") - @test region.centroid.lat == 41.83956 - @test region.centroid.lon == -88.08857 - @test region.population == 922_921 -end - -# @testset "geodb_query (2018-us-zcta)" begin -# region = RELOG.geodb_query("2018-us-zcta:60439") -# @test region.centroid.lat == 41.68241 -# @test region.centroid.lon == -87.98954 -# end - -@testset "geodb_query (us-state)" begin - region = RELOG.geodb_query("us-state:IL") - @test region.centroid.lat == 39.73939 - @test region.centroid.lon == -89.50414 - @test region.population == 12_671_821 -end diff --git a/test/instance/parse_test.jl b/test/instance/parse_test.jl deleted file mode 100644 index f4d0527..0000000 --- a/test/instance/parse_test.jl +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright (C) 2020 Argonne National Laboratory -# Written by Alinson Santos Xavier - -using RELOG - -@testset "parse" begin - basedir = dirname(@__FILE__) - instance = RELOG.parsefile("$basedir/../../instances/s1.json") - - centers = instance.collection_centers - plants = instance.plants - products = instance.products - location_name_to_plant = Dict(p.location_name => p for p in plants) - product_name_to_product = Dict(p.name => p for p in products) - - @test length(centers) == 10 - @test centers[1].name == "C1" - @test centers[1].latitude == 7 - @test centers[1].latitude == 7 - @test centers[1].longitude == 7 - @test centers[1].amount == [934.56, 934.56] - @test centers[1].product.name == "P1" - - @test length(plants) == 6 - - plant = location_name_to_plant["L1"] - @test plant.plant_name == "F1" - @test plant.location_name == "L1" - @test plant.input.name == "P1" - @test plant.latitude == 0 - @test plant.longitude == 0 - - @test length(plant.sizes) == 2 - @test plant.sizes[1].capacity == 250 - @test plant.sizes[1].opening_cost == [500, 500] - @test plant.sizes[1].fixed_operating_cost == [30, 30] - @test plant.sizes[1].variable_operating_cost == [30, 30] - @test plant.sizes[2].capacity == 1000 - @test plant.sizes[2].opening_cost == [1250, 1250] - @test plant.sizes[2].fixed_operating_cost == [30, 30] - @test plant.sizes[2].variable_operating_cost == [30, 30] - - p1 = product_name_to_product["P1"] - @test p1.disposal_limit == [1.0, 1.0] - @test p1.disposal_cost == [-1000.0, -1000.0] - - p2 = product_name_to_product["P2"] - @test p2.disposal_limit == [0.0, 0.0] - @test p2.disposal_cost == [0.0, 0.0] - - p3 = product_name_to_product["P3"] - @test length(plant.output) == 2 - @test plant.output[p2] == 0.2 - @test plant.output[p3] == 0.5 - @test plant.disposal_limit[p2] == [1, 1] - @test plant.disposal_limit[p3] == [1, 1] - @test plant.disposal_cost[p2] == [-10, -10] - @test plant.disposal_cost[p3] == [-10, -10] - - plant = location_name_to_plant["L3"] - @test plant.location_name == "L3" - @test plant.input.name == "P2" - @test plant.latitude == 25 - @test plant.longitude == 65 - - @test length(plant.sizes) == 2 - @test plant.sizes[1].capacity == 1000.0 - @test plant.sizes[1].opening_cost == [3000, 3000] - @test plant.sizes[1].fixed_operating_cost == [50, 50] - @test plant.sizes[1].variable_operating_cost == [50, 50] - @test plant.sizes[1] == plant.sizes[2] - - p4 = product_name_to_product["P4"] - @test plant.output[p3] == 0.05 - @test plant.output[p4] == 0.8 - @test plant.disposal_limit[p3] == [1e8, 1e8] - @test plant.disposal_limit[p4] == [0, 0] -end - -@testset "parse (geodb)" begin - basedir = dirname(@__FILE__) - instance = RELOG.parsefile("$basedir/../../instances/s2.json") - - centers = instance.collection_centers - @test centers[1].name == "C1" - @test centers[1].latitude == 41.83956 - @test centers[1].longitude == -88.08857 -end - -# @testset "parse (invalid)" begin -# basedir = dirname(@__FILE__) -# @test_throws ErrorException RELOG.parsefile("$basedir/../fixtures/s1-wrong-length.json") -# end diff --git a/test/model/build_test.jl b/test/model/build_test.jl deleted file mode 100644 index 5dc554a..0000000 --- a/test/model/build_test.jl +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (C) 2020 Argonne National Laboratory -# Written by Alinson Santos Xavier - -using RELOG, Cbc, JuMP, Printf, JSON, MathOptInterface.FileFormats - -@testset "build" begin - basedir = dirname(@__FILE__) - instance = RELOG.parsefile("$basedir/../../instances/s1.json") - graph = RELOG.build_graph(instance) - model = RELOG.build_model(instance, graph, Cbc.Optimizer) - set_optimizer_attribute(model, "logLevel", 0) - - process_node_by_location_name = - Dict(n.location.location_name => n for n in graph.process_nodes) - - shipping_node_by_loc_and_prod_names = Dict( - (n.location.location_name, n.product.name) => n for n in graph.plant_shipping_nodes - ) - - @test length(model[:flow]) == 76 - @test length(model[:plant_dispose]) == 16 - @test length(model[:open_plant]) == 12 - @test length(model[:capacity]) == 12 - @test length(model[:expansion]) == 12 - - l1 = process_node_by_location_name["L1"] - v = model[:capacity][l1, 1] - @test lower_bound(v) == 0.0 - @test upper_bound(v) == 1000.0 - - v = model[:expansion][l1, 1] - @test lower_bound(v) == 0.0 - @test upper_bound(v) == 750.0 - - v = model[:plant_dispose][shipping_node_by_loc_and_prod_names["L1", "P2"], 1] - @test lower_bound(v) == 0.0 - @test upper_bound(v) == 1.0 -end diff --git a/test/model/resolve_test.jl b/test/model/resolve_test.jl deleted file mode 100644 index 9021000..0000000 --- a/test/model/resolve_test.jl +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (C) 2020 Argonne National Laboratory -# Written by Alinson Santos Xavier - -using RELOG - -basedir = @__DIR__ - -@testset "Resolve" begin - # Shoud not crash - filename = "$basedir/../../instances/s1.json" - solution_old, model_old = RELOG.solve(filename, return_model = true) - solution_new = RELOG.resolve(model_old, filename) -end diff --git a/test/model/solve_test.jl b/test/model/solve_test.jl deleted file mode 100644 index 0f03bd4..0000000 --- a/test/model/solve_test.jl +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright (C) 2020 Argonne National Laboratory -# Written by Alinson Santos Xavier - -using RELOG, Cbc, JuMP, Printf, JSON, MathOptInterface.FileFormats - -basedir = dirname(@__FILE__) - -@testset "solve (exact)" begin - solution_filename_a = tempname() - solution_filename_b = tempname() - solution = RELOG.solve("$basedir/../../instances/s1.json", output = solution_filename_a) - - @test isfile(solution_filename_a) - - RELOG.write(solution, solution_filename_b) - @test isfile(solution_filename_b) - - @test "Costs" in keys(solution) - @test "Fixed operating (\$)" in keys(solution["Costs"]) - @test "Transportation (\$)" in keys(solution["Costs"]) - @test "Variable operating (\$)" in keys(solution["Costs"]) - @test "Total (\$)" in keys(solution["Costs"]) - - @test "Plants" in keys(solution) - @test "F1" in keys(solution["Plants"]) - @test "F2" in keys(solution["Plants"]) - @test "F3" in keys(solution["Plants"]) - @test "F4" in keys(solution["Plants"]) - - @test "Products" in keys(solution) - @test "P1" in keys(solution["Products"]) - @test "C1" in keys(solution["Products"]["P1"]) - @test "Dispose (tonne)" in keys(solution["Products"]["P1"]["C1"]) - - total_disposal = - sum([loc["Dispose (tonne)"] for loc in values(solution["Products"]["P1"])]) - @test total_disposal == [1.0, 1.0] -end - -@testset "solve (heuristic)" begin - # Should not crash - solution = RELOG.solve("$basedir/../../instances/s1.json", heuristic = true) -end - -@testset "solve (infeasible)" begin - json = JSON.parsefile("$basedir/../../instances/s1.json") - for (location_name, location_dict) in json["products"]["P1"]["initial amounts"] - location_dict["amount (tonne)"] *= 1000 - end - @test_throws ErrorException("No solution available") RELOG.solve(RELOG.parse(json)) -end - -@testset "solve (with storage)" begin - basedir = dirname(@__FILE__) - filename = "$basedir/../fixtures/storage.json" - instance = RELOG.parsefile(filename) - @test instance.plants[1].storage_limit == 50.0 - @test instance.plants[1].storage_cost == [2.0, 1.5, 1.0] - - solution = RELOG.solve(filename) - plant_dict = solution["Plants"]["mega plant"]["Chicago"] - @test plant_dict["Variable operating cost (\$)"] == [500.0, 0.0, 100.0] - @test plant_dict["Process (tonne)"] == [50.0, 0.0, 50.0] - @test plant_dict["Storage (tonne)"] == [50.0, 50.0, 0.0] - @test plant_dict["Storage cost (\$)"] == [100.0, 75.0, 0.0] - - @test solution["Costs"]["Variable operating (\$)"] == [500.0, 0.0, 100.0] - @test solution["Costs"]["Storage (\$)"] == [100.0, 75.0, 0.0] - @test solution["Costs"]["Total (\$)"] == [600.0, 75.0, 100.0] -end diff --git a/test/reports_test.jl b/test/reports_test.jl deleted file mode 100644 index 9193977..0000000 --- a/test/reports_test.jl +++ /dev/null @@ -1,21 +0,0 @@ -# RELOG: Reverse Logistics Optimization -# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. -# Released under the modified BSD license. See COPYING.md for more details. - -using RELOG, JSON, GZip - -basedir = @__DIR__ - -@testset "Reports" begin - @testset "from solve" begin - solution = RELOG.solve("$basedir/../instances/s1.json") - tmp_filename = tempname() - # The following should not crash - RELOG.write_plant_emissions_report(solution, tmp_filename) - RELOG.write_plant_outputs_report(solution, tmp_filename) - RELOG.write_plants_report(solution, tmp_filename) - RELOG.write_products_report(solution, tmp_filename) - RELOG.write_transportation_emissions_report(solution, tmp_filename) - RELOG.write_transportation_report(solution, tmp_filename) - end -end diff --git a/test/runtests.jl b/test/runtests.jl deleted file mode 100644 index 1da75c7..0000000 --- a/test/runtests.jl +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (C) 2020 Argonne National Laboratory -# Written by Alinson Santos Xavier - -using Test - -@testset "RELOG" begin - @testset "Instance" begin - include("instance/compress_test.jl") - include("instance/geodb_test.jl") - include("instance/parse_test.jl") - end - @testset "Graph" begin - include("graph/build_test.jl") - include("graph/dist_test.jl") - end - @testset "Model" begin - include("model/build_test.jl") - include("model/solve_test.jl") - include("model/resolve_test.jl") - end - include("reports_test.jl") -end diff --git a/test/src/RELOGT.jl b/test/src/RELOGT.jl new file mode 100644 index 0000000..2691480 --- /dev/null +++ b/test/src/RELOGT.jl @@ -0,0 +1,51 @@ +module RELOGT + +using Test +using JuliaFormatter + +include("instance/compress_test.jl") +include("instance/geodb_test.jl") +include("instance/parse_test.jl") +include("graph/build_test.jl") +include("graph/dist_test.jl") +include("model/build_test.jl") +include("model/solve_test.jl") +include("model/resolve_test.jl") +include("reports_test.jl") + +basedir = dirname(@__FILE__) + +function fixture(path::String)::String + return "$basedir/../fixtures/$path" +end + +function runtests() + @testset "RELOG" begin + @testset "instance" begin + instance_compress_test() + instance_geodb_test() + instance_parse_test() + end + @testset "graph" begin + graph_build_test() + graph_dist_test() + end + @testset "model" begin + model_build_test() + model_solve_test() + model_resolve_test() + end + reports_test() + end + return +end + +function format() + JuliaFormatter.format(basedir, verbose = true) + JuliaFormatter.format("$basedir/../../src", verbose = true) + return +end + +export runtests, format + +end # module RELOGT diff --git a/test/src/graph/build_test.jl b/test/src/graph/build_test.jl new file mode 100644 index 0000000..070f899 --- /dev/null +++ b/test/src/graph/build_test.jl @@ -0,0 +1,40 @@ +# Copyright (C) 2020 Argonne National Laboratory +# Written by Alinson Santos Xavier + +using RELOG + +function graph_build_test() + @testset "build_graph" begin + instance = RELOG.parsefile(fixture("s1.json")) + graph = RELOG.build_graph(instance) + process_node_by_location_name = + Dict(n.location.location_name => n for n in graph.process_nodes) + + @test length(graph.plant_shipping_nodes) == 8 + @test length(graph.collection_shipping_nodes) == 10 + @test length(graph.process_nodes) == 6 + + node = graph.collection_shipping_nodes[1] + @test node.location.name == "C1" + @test length(node.incoming_arcs) == 0 + @test length(node.outgoing_arcs) == 2 + @test node.outgoing_arcs[1].source.location.name == "C1" + @test node.outgoing_arcs[1].dest.location.plant_name == "F1" + @test node.outgoing_arcs[1].dest.location.location_name == "L1" + @test node.outgoing_arcs[1].values["distance"] == 1695.364 + + node = process_node_by_location_name["L1"] + @test node.location.plant_name == "F1" + @test node.location.location_name == "L1" + @test length(node.incoming_arcs) == 10 + @test length(node.outgoing_arcs) == 2 + + node = process_node_by_location_name["L3"] + @test node.location.plant_name == "F2" + @test node.location.location_name == "L3" + @test length(node.incoming_arcs) == 2 + @test length(node.outgoing_arcs) == 2 + + @test length(graph.arcs) == 38 + end +end diff --git a/test/src/graph/dist_test.jl b/test/src/graph/dist_test.jl new file mode 100644 index 0000000..8dd084a --- /dev/null +++ b/test/src/graph/dist_test.jl @@ -0,0 +1,27 @@ +# RELOG: Reverse Logistics Optimization +# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. +# Released under the modified BSD license. See COPYING.md for more details. + +using RELOG + +function graph_dist_test() + @testset "KnnDrivingDistance" begin + # Euclidean distance between Chicago and Indianapolis + @test RELOG._calculate_distance( + 41.866, + -87.656, + 39.764, + -86.148, + RELOG.EuclideanDistance(), + ) == 265.818 + + # Approximate driving distance between Chicago and Indianapolis + @test RELOG._calculate_distance( + 41.866, + -87.656, + 39.764, + -86.148, + RELOG.KnnDrivingDistance(), + ) == 316.43 + end +end diff --git a/test/src/instance/compress_test.jl b/test/src/instance/compress_test.jl new file mode 100644 index 0000000..6652c63 --- /dev/null +++ b/test/src/instance/compress_test.jl @@ -0,0 +1,54 @@ +# Copyright (C) 2020 Argonne National Laboratory +# Written by Alinson Santos Xavier + +using RELOG + +function instance_compress_test() + @testset "compress" begin + instance = RELOG.parsefile(fixture("s1.json")) + compressed = RELOG._compress(instance) + + product_name_to_product = Dict(p.name => p for p in compressed.products) + location_name_to_facility = Dict() + for p in compressed.plants + location_name_to_facility[p.location_name] = p + end + for c in compressed.collection_centers + location_name_to_facility[c.name] = c + end + + p1 = product_name_to_product["P1"] + p2 = product_name_to_product["P2"] + p3 = product_name_to_product["P3"] + c1 = location_name_to_facility["C1"] + l1 = location_name_to_facility["L1"] + + @test compressed.time == 1 + @test compressed.building_period == [1] + + @test p1.name == "P1" + @test p1.transportation_cost ≈ [0.015] + @test p1.transportation_energy ≈ [0.115] + @test p1.transportation_emissions["CO2"] ≈ [0.051] + @test p1.transportation_emissions["CH4"] ≈ [0.0025] + + @test c1.name == "C1" + @test c1.amount ≈ [1869.12] + + @test l1.plant_name == "F1" + @test l1.location_name == "L1" + @test l1.energy ≈ [0.115] + @test l1.emissions["CO2"] ≈ [0.051] + @test l1.emissions["CH4"] ≈ [0.0025] + @test l1.sizes[1].opening_cost ≈ [500] + @test l1.sizes[2].opening_cost ≈ [1250] + @test l1.sizes[1].fixed_operating_cost ≈ [60] + @test l1.sizes[2].fixed_operating_cost ≈ [60] + @test l1.sizes[1].variable_operating_cost ≈ [30] + @test l1.sizes[2].variable_operating_cost ≈ [30] + @test l1.disposal_limit[p2] ≈ [2.0] + @test l1.disposal_limit[p3] ≈ [2.0] + @test l1.disposal_cost[p2] ≈ [-10.0] + @test l1.disposal_cost[p3] ≈ [-10.0] + end +end diff --git a/test/src/instance/geodb_test.jl b/test/src/instance/geodb_test.jl new file mode 100644 index 0000000..f128ccc --- /dev/null +++ b/test/src/instance/geodb_test.jl @@ -0,0 +1,27 @@ +# RELOG: Reverse Logistics Optimization +# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. +# Released under the modified BSD license. See COPYING.md for more details. + +using RELOG + +function instance_geodb_test() + @testset "geodb_query (2018-us-county)" begin + region = RELOG.geodb_query("2018-us-county:17043") + @test region.centroid.lat == 41.83956 + @test region.centroid.lon == -88.08857 + @test region.population == 922_921 + end + + # @testset "geodb_query (2018-us-zcta)" begin + # region = RELOG.geodb_query("2018-us-zcta:60439") + # @test region.centroid.lat == 41.68241 + # @test region.centroid.lon == -87.98954 + # end + + @testset "geodb_query (us-state)" begin + region = RELOG.geodb_query("us-state:IL") + @test region.centroid.lat == 39.73939 + @test region.centroid.lon == -89.50414 + @test region.population == 12_671_821 + end +end diff --git a/test/src/instance/parse_test.jl b/test/src/instance/parse_test.jl new file mode 100644 index 0000000..16288e1 --- /dev/null +++ b/test/src/instance/parse_test.jl @@ -0,0 +1,87 @@ +# Copyright (C) 2020 Argonne National Laboratory +# Written by Alinson Santos Xavier + +using RELOG + +function instance_parse_test() + @testset "parse" begin + instance = RELOG.parsefile(fixture("s1.json")) + + centers = instance.collection_centers + plants = instance.plants + products = instance.products + location_name_to_plant = Dict(p.location_name => p for p in plants) + product_name_to_product = Dict(p.name => p for p in products) + + @test length(centers) == 10 + @test centers[1].name == "C1" + @test centers[1].latitude == 7 + @test centers[1].latitude == 7 + @test centers[1].longitude == 7 + @test centers[1].amount == [934.56, 934.56] + @test centers[1].product.name == "P1" + + @test length(plants) == 6 + + plant = location_name_to_plant["L1"] + @test plant.plant_name == "F1" + @test plant.location_name == "L1" + @test plant.input.name == "P1" + @test plant.latitude == 0 + @test plant.longitude == 0 + + @test length(plant.sizes) == 2 + @test plant.sizes[1].capacity == 250 + @test plant.sizes[1].opening_cost == [500, 500] + @test plant.sizes[1].fixed_operating_cost == [30, 30] + @test plant.sizes[1].variable_operating_cost == [30, 30] + @test plant.sizes[2].capacity == 1000 + @test plant.sizes[2].opening_cost == [1250, 1250] + @test plant.sizes[2].fixed_operating_cost == [30, 30] + @test plant.sizes[2].variable_operating_cost == [30, 30] + + p1 = product_name_to_product["P1"] + @test p1.disposal_limit == [1.0, 1.0] + @test p1.disposal_cost == [-1000.0, -1000.0] + + p2 = product_name_to_product["P2"] + @test p2.disposal_limit == [0.0, 0.0] + @test p2.disposal_cost == [0.0, 0.0] + + p3 = product_name_to_product["P3"] + @test length(plant.output) == 2 + @test plant.output[p2] == 0.2 + @test plant.output[p3] == 0.5 + @test plant.disposal_limit[p2] == [1, 1] + @test plant.disposal_limit[p3] == [1, 1] + @test plant.disposal_cost[p2] == [-10, -10] + @test plant.disposal_cost[p3] == [-10, -10] + + plant = location_name_to_plant["L3"] + @test plant.location_name == "L3" + @test plant.input.name == "P2" + @test plant.latitude == 25 + @test plant.longitude == 65 + + @test length(plant.sizes) == 2 + @test plant.sizes[1].capacity == 1000.0 + @test plant.sizes[1].opening_cost == [3000, 3000] + @test plant.sizes[1].fixed_operating_cost == [50, 50] + @test plant.sizes[1].variable_operating_cost == [50, 50] + @test plant.sizes[1] == plant.sizes[2] + + p4 = product_name_to_product["P4"] + @test plant.output[p3] == 0.05 + @test plant.output[p4] == 0.8 + @test plant.disposal_limit[p3] == [1e8, 1e8] + @test plant.disposal_limit[p4] == [0, 0] + end + + @testset "parse (geodb)" begin + instance = RELOG.parsefile(fixture("s2.json")) + centers = instance.collection_centers + @test centers[1].name == "C1" + @test centers[1].latitude == 41.83956 + @test centers[1].longitude == -88.08857 + end +end diff --git a/test/src/model/build_test.jl b/test/src/model/build_test.jl new file mode 100644 index 0000000..3c111ea --- /dev/null +++ b/test/src/model/build_test.jl @@ -0,0 +1,40 @@ +# Copyright (C) 2020 Argonne National Laboratory +# Written by Alinson Santos Xavier + +using RELOG, Cbc, JuMP, Printf, JSON, MathOptInterface.FileFormats + +function model_build_test() + @testset "build" begin + instance = RELOG.parsefile(fixture("s1.json")) + graph = RELOG.build_graph(instance) + model = RELOG.build_model(instance, graph, Cbc.Optimizer) + set_optimizer_attribute(model, "logLevel", 0) + + process_node_by_location_name = + Dict(n.location.location_name => n for n in graph.process_nodes) + + shipping_node_by_loc_and_prod_names = Dict( + (n.location.location_name, n.product.name) => n for + n in graph.plant_shipping_nodes + ) + + @test length(model[:flow]) == 76 + @test length(model[:plant_dispose]) == 16 + @test length(model[:open_plant]) == 12 + @test length(model[:capacity]) == 12 + @test length(model[:expansion]) == 12 + + l1 = process_node_by_location_name["L1"] + v = model[:capacity][l1, 1] + @test lower_bound(v) == 0.0 + @test upper_bound(v) == 1000.0 + + v = model[:expansion][l1, 1] + @test lower_bound(v) == 0.0 + @test upper_bound(v) == 750.0 + + v = model[:plant_dispose][shipping_node_by_loc_and_prod_names["L1", "P2"], 1] + @test lower_bound(v) == 0.0 + @test upper_bound(v) == 1.0 + end +end diff --git a/test/src/model/resolve_test.jl b/test/src/model/resolve_test.jl new file mode 100644 index 0000000..32e3e23 --- /dev/null +++ b/test/src/model/resolve_test.jl @@ -0,0 +1,13 @@ +# Copyright (C) 2020 Argonne National Laboratory +# Written by Alinson Santos Xavier + +using RELOG + +function model_resolve_test() + @testset "Resolve" begin + # Shoud not crash + filename = fixture("s1.json") + solution_old, model_old = RELOG.solve(filename, return_model = true) + solution_new = RELOG.resolve(model_old, filename) + end +end diff --git a/test/src/model/solve_test.jl b/test/src/model/solve_test.jl new file mode 100644 index 0000000..ecb948a --- /dev/null +++ b/test/src/model/solve_test.jl @@ -0,0 +1,70 @@ +# Copyright (C) 2020 Argonne National Laboratory +# Written by Alinson Santos Xavier + +using RELOG, Cbc, JuMP, Printf, JSON, MathOptInterface.FileFormats + + +function model_solve_test() + @testset "solve (exact)" begin + solution_filename_a = tempname() + solution_filename_b = tempname() + solution = RELOG.solve(fixture("s1.json"), output = solution_filename_a) + + @test isfile(solution_filename_a) + + RELOG.write(solution, solution_filename_b) + @test isfile(solution_filename_b) + + @test "Costs" in keys(solution) + @test "Fixed operating (\$)" in keys(solution["Costs"]) + @test "Transportation (\$)" in keys(solution["Costs"]) + @test "Variable operating (\$)" in keys(solution["Costs"]) + @test "Total (\$)" in keys(solution["Costs"]) + + @test "Plants" in keys(solution) + @test "F1" in keys(solution["Plants"]) + @test "F2" in keys(solution["Plants"]) + @test "F3" in keys(solution["Plants"]) + @test "F4" in keys(solution["Plants"]) + + @test "Products" in keys(solution) + @test "P1" in keys(solution["Products"]) + @test "C1" in keys(solution["Products"]["P1"]) + @test "Dispose (tonne)" in keys(solution["Products"]["P1"]["C1"]) + + total_disposal = + sum([loc["Dispose (tonne)"] for loc in values(solution["Products"]["P1"])]) + @test total_disposal == [1.0, 1.0] + end + + @testset "solve (heuristic)" begin + # Should not crash + solution = RELOG.solve(fixture("s1.json"), heuristic = true) + end + + @testset "solve (infeasible)" begin + json = JSON.parsefile(fixture("s1.json")) + for (location_name, location_dict) in json["products"]["P1"]["initial amounts"] + location_dict["amount (tonne)"] *= 1000 + end + @test_throws ErrorException("No solution available") RELOG.solve(RELOG.parse(json)) + end + + @testset "solve (with storage)" begin + filename = fixture("storage.json") + instance = RELOG.parsefile(filename) + @test instance.plants[1].storage_limit == 50.0 + @test instance.plants[1].storage_cost == [2.0, 1.5, 1.0] + + solution = RELOG.solve(filename) + plant_dict = solution["Plants"]["mega plant"]["Chicago"] + @test plant_dict["Variable operating cost (\$)"] == [500.0, 0.0, 100.0] + @test plant_dict["Process (tonne)"] == [50.0, 0.0, 50.0] + @test plant_dict["Storage (tonne)"] == [50.0, 50.0, 0.0] + @test plant_dict["Storage cost (\$)"] == [100.0, 75.0, 0.0] + + @test solution["Costs"]["Variable operating (\$)"] == [500.0, 0.0, 100.0] + @test solution["Costs"]["Storage (\$)"] == [100.0, 75.0, 0.0] + @test solution["Costs"]["Total (\$)"] == [600.0, 75.0, 100.0] + end +end diff --git a/test/src/reports_test.jl b/test/src/reports_test.jl new file mode 100644 index 0000000..3f3971b --- /dev/null +++ b/test/src/reports_test.jl @@ -0,0 +1,21 @@ +# RELOG: Reverse Logistics Optimization +# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. +# Released under the modified BSD license. See COPYING.md for more details. + +using RELOG, JSON, GZip + +function reports_test() + @testset "reports" begin + @testset "from solve" begin + solution = RELOG.solve(fixture("s1.json")) + tmp_filename = tempname() + # The following should not crash + RELOG.write_plant_emissions_report(solution, tmp_filename) + RELOG.write_plant_outputs_report(solution, tmp_filename) + RELOG.write_plants_report(solution, tmp_filename) + RELOG.write_products_report(solution, tmp_filename) + RELOG.write_transportation_emissions_report(solution, tmp_filename) + RELOG.write_transportation_report(solution, tmp_filename) + end + end +end