lol

qgis: add nixos tests

Add NixOS test for QGIS and QGIS-LTR. This test creates QGIS vector
memory layer containing Nix snowflake. This proves that application can
successfully start and Python bindings are working.

By default, Python script is executed in non-interactive mode and QGIS
is closed after script is finished. This script can be also executed
interactively by running following command:

```
nix-build -A qgis
QGIS_TEST_INTERACTIVE=True ./result/bin/qgis --code pkgs/applications/gis/qgis/test.py
```

In this case, QGIS is not automatically closed.

+108 -4
+4 -2
nixos/tests/all-tests.nix
··· 669 669 qboot = handleTestOn ["x86_64-linux" "i686-linux"] ./qboot.nix {}; 670 670 qemu-vm-restrictnetwork = handleTest ./qemu-vm-restrictnetwork.nix {}; 671 671 qemu-vm-volatile-root = runTest ./qemu-vm-volatile-root.nix; 672 - quorum = handleTest ./quorum.nix {}; 673 - quake3 = handleTest ./quake3.nix {}; 672 + qgis = handleTest ./qgis.nix { qgisPackage = pkgs.qgis; }; 673 + qgis-ltr = handleTest ./qgis.nix { qgisPackage = pkgs.qgis-ltr; }; 674 674 qownnotes = handleTest ./qownnotes.nix {}; 675 + quake3 = handleTest ./quake3.nix {}; 676 + quorum = handleTest ./quorum.nix {}; 675 677 rabbitmq = handleTest ./rabbitmq.nix {}; 676 678 radarr = handleTest ./radarr.nix {}; 677 679 radicale = handleTest ./radicale.nix {};
+30
nixos/tests/qgis.nix
··· 1 + import ./make-test-python.nix ({ pkgs, lib, qgisPackage, ... }: 2 + let 3 + testScript = pkgs.writeTextFile { 4 + name = "qgis-test.py"; 5 + text = (builtins.readFile ../../pkgs/applications/gis/qgis/test.py); 6 + }; 7 + in 8 + { 9 + name = "qgis"; 10 + meta = { 11 + maintainers = with lib; [ teams.geospatial.members ]; 12 + }; 13 + 14 + nodes = { 15 + machine = { pkgs, ... }: { 16 + virtualisation.diskSize = 2 * 1024; 17 + 18 + imports = [ ./common/x11.nix ]; 19 + environment.systemPackages = [ qgisPackage ]; 20 + 21 + }; 22 + }; 23 + 24 + testScript = '' 25 + start_all() 26 + 27 + machine.succeed("${qgisPackage}/bin/qgis --version | grep 'QGIS ${qgisPackage.version}'") 28 + machine.succeed("${qgisPackage}/bin/qgis --code ${testScript}") 29 + ''; 30 + })
+5 -1
pkgs/applications/gis/qgis/default.nix
··· 1 1 { lib 2 2 , makeWrapper 3 + , nixosTests 3 4 , symlinkJoin 4 5 5 6 , extraPythonPackages ? (ps: [ ]) ··· 33 34 --set PYTHONPATH $program_PYTHONPATH 34 35 ''; 35 36 36 - passthru.unwrapped = qgis-unwrapped; 37 + passthru = { 38 + unwrapped = qgis-unwrapped; 39 + tests.qgis = nixosTests.qgis; 40 + }; 37 41 38 42 meta = qgis-unwrapped.meta; 39 43 }
+5 -1
pkgs/applications/gis/qgis/ltr.nix
··· 1 1 { lib 2 2 , makeWrapper 3 + , nixosTests 3 4 , symlinkJoin 4 5 5 6 , extraPythonPackages ? (ps: [ ]) ··· 33 34 --set PYTHONPATH $program_PYTHONPATH 34 35 ''; 35 36 36 - passthru.unwrapped = qgis-ltr-unwrapped; 37 + passthru = { 38 + unwrapped = qgis-ltr-unwrapped; 39 + tests.qgis-ltr = nixosTests.qgis-ltr; 40 + }; 37 41 38 42 inherit (qgis-ltr-unwrapped) meta; 39 43 }
+64
pkgs/applications/gis/qgis/test.py
··· 1 + # QGIS test script. 2 + # This script will create vector memory layer containing Nix snowflake. 3 + 4 + # Set QGIS_TEST_INTERACTIVE=True to run this script in interactive mode (and see 5 + # Nix snowflake). 6 + 7 + # Run script as following: 8 + # QGIS_TEST_INTERACTIVE=True ./result/bin/qgis --code pkgs/applications/gis/qgis/test.py 9 + 10 + import os 11 + 12 + test_interactive = eval(os.getenv("QGIS_TEST_INTERACTIVE", "False")) 13 + 14 + def test(test_interactive=False): 15 + 16 + import osgeo # just to check if geo python modules are available 17 + from qgis.core import QgsVectorLayer, QgsFeature, QgsGeometry, QgsProject 18 + 19 + # Nix snowflake as WKT 20 + WKT = """ 21 + MULTIPOLYGON ( 22 + ((37.10819200000000251 45.01934500000000128, 41.42360200000000248 45.0228350000000006, 43.98593199999999825 46.39836900000000242, 51.11554000000000286 46.39135900000000134, 52.20562400000000025 46.98079299999999847, 51.13812500000000227 47.55708200000000119, 46.12925599999999804 47.56117799999999818, 48.65136199999999889 48.91279899999999969, 46.46644299999999816 50.06610299999999825, 37.10819200000000251 45.01934500000000128)), 23 + ((36.37806400000000195 49.06532800000000094, 34.21064499999999953 50.22733199999999698, 29.10392099999999971 50.23055699999999746, 25.55861099999999908 52.15672200000000203, 23.37426999999999921 52.15597100000000097, 22.30527299999999968 51.57995100000000122, 24.79831000000000074 50.22714599999999763, 19.77820099999999925 50.23147999999999769, 17.66315000000000168 49.06561399999999651, 36.37806400000000195 49.06532800000000094)), 24 + ((25.51021400000000128 46.84120599999999968, 23.36222199999999916 45.67570500000000067, 25.90661599999999964 44.29694800000000043, 22.32231799999999922 42.37779100000000199, 23.41657500000000169 41.78910799999999881, 25.55307200000000023 41.78884599999999949, 28.06890399999999985 43.13755299999999693, 30.56690599999999947 41.78159999999999741, 34.86687599999999776 41.79416100000000256, 25.51021400000000128 46.84120599999999968)), 25 + ((29.60533099999999962 44.88583400000000267, 31.77274900000000102 43.72382000000000346, 36.87947299999999728 43.7205939999999984, 40.42478299999999791 41.79442999999999842, 42.60912400000000133 41.7951929999999976, 43.67812200000000189 42.37121299999999735, 41.18508400000000336 43.72401599999999888, 46.20519399999999877 43.71968400000000088, 48.32024400000000242 44.885548, 29.60533099999999962 44.88583400000000267)), 26 + ((28.88739899999999849 48.92013800000000145, 24.57198899999999853 48.9166450000000026, 22.0096589999999992 47.54111400000000032, 14.88005199999999917 47.54812199999999933, 13.78996700000000075 46.95868999999999716, 14.85746600000000051 46.38240100000000155, 19.86633600000000044 46.37830199999999792, 17.34422899999999856 45.02668100000000351, 19.52914900000000031 43.87337800000000243, 28.88739899999999849 48.92013800000000145)), 27 + ((25.52133699999999905 46.84445300000000145, 23.37334500000000048 45.67894900000000291, 25.91773900000000097 44.30019200000000268, 22.33344200000000157 42.38103699999999918, 23.4276990000000005 41.79235400000000311, 25.56419500000000156 41.79209199999999669, 28.08002700000000118 43.14079900000000123, 30.57802999999999827 41.78484600000000171, 34.87800000000000011 41.79740699999999975, 25.52133699999999905 46.84445300000000145)), 28 + ((25.52133699999999905 46.84445300000000145, 23.37334500000000048 45.67895099999999786, 25.91773900000000097 44.30019200000000268, 22.33344200000000157 42.38103699999999918, 23.4276990000000005 41.79235400000000311, 25.56419500000000156 41.79209199999999669, 28.08002700000000118 43.14079900000000123, 30.57802999999999827 41.78484600000000171, 34.87800000000000011 41.79740699999999975, 25.52133699999999905 46.84445300000000145)), 29 + ((25.51021400000000128 46.84120599999999968, 23.36222199999999916 45.67570500000000067, 25.90661599999999964 44.29694800000000043, 22.32231799999999922 42.37779100000000199, 23.41657500000000169 41.78910799999999881, 25.55307200000000023 41.78884599999999949, 28.06890399999999985 43.13755299999999693, 30.56690599999999947 41.78159999999999741, 34.86687599999999776 41.79416100000000256, 25.51021400000000128 46.84120599999999968)), 30 + ((40.49807200000000051 47.09720099999999832, 42.64606299999999806 48.26270199999999733, 40.10166999999999859 49.64145899999999756, 43.685966999999998 51.56061600000000311, 42.59170999999999907 52.14929899999999918, 40.45521399999999801 52.1495609999999985, 37.93938099999999736 50.80085400000000107, 35.44137899999999775 52.15680700000000058, 31.14140899999999945 52.14424700000000001, 40.49807200000000051 47.09720099999999832)), 31 + ) 32 + """ 33 + 34 + layer = QgsVectorLayer('Polygon?crs=epsg:3857', 'QGIS-on-Nix', 'memory') 35 + provider = layer.dataProvider() 36 + 37 + polygon = QgsFeature() 38 + geom = QgsGeometry.fromWkt(WKT) 39 + polygon.setGeometry(geom) 40 + provider.addFeatures([polygon]) 41 + 42 + layer.updateExtents() 43 + QgsProject.instance().addMapLayers([layer]) 44 + 45 + # Make sure our test layer contains exactly one feature 46 + assert layer.featureCount() == 1 47 + 48 + if not test_interactive: 49 + QgsProject.instance().removeMapLayer(layer) 50 + QgsProject.instance().clear() 51 + 52 + try: 53 + test(test_interactive=test_interactive) 54 + 55 + if not test_interactive: 56 + print("QGIS test script was successfully executed.") 57 + os._exit(0) # iface.actionExit().trigger() doesn't work 58 + 59 + except Exception as e: 60 + if not test_interactive: 61 + print("QGIS test script has failed.") 62 + print("Error message: {}".format(e)) 63 + os._exit(1) 64 +