@ParameterizedTest
  @ValueSource(strings = {
    "",
    "--write-threads=2 --process-threads=2 --feature-read-threads=2 --threads=4",
    "--free-osm-after-read",
    "--compress-temp",
    "--osm-parse-node-bounds",
    "--output-format=pmtiles",
    "--output-format=csv",
    "--output-format=tsv",
    "--output-format=proto",
    "--output-format=pbf",
    "--output-format=json",
    "--output-format=files",
    "--tile-compression=none",
    "--tile-compression=gzip",
    "--output-layerstats",
    "--max-point-buffer=1",
    "--osm-test-path=monaco-latest.lz4.osm.pbf",
  })
  void testPlanetilerRunner(String args) throws Exception {
    var argParsed = Arguments.fromArgs(args.split(" "));
    Path originalOsm =
      TestUtils.pathToResource(argParsed.getString("osm-test-path", "osm-test-path", "monaco-latest.osm.pbf"));
    Path tempOsm = tempDir.resolve("monaco-temp.osm.pbf");
    final TileCompression tileCompression = extractTileCompression(args);

    final TileArchiveConfig.Format format = extractFormat(args);
    final String outputUri;
    final Path outputPath;
    switch (format) {
      case FILES -> {
        outputPath = tempDir.resolve("output");
        outputUri = outputPath.toString() + "?format=files";
      }
      default -> {
        outputPath = tempDir.resolve("output." + format.id());
        outputUri = outputPath.toString();
      }
    }

    final ReadableTileArchiveFactory readableTileArchiveFactory = switch (format) {
      case MBTILES -> Mbtiles::newReadOnlyDatabase;
      case CSV -> p -> InMemoryStreamArchive.fromCsv(p, ",");
      case TSV -> p -> InMemoryStreamArchive.fromCsv(p, "\t");
      case JSON -> InMemoryStreamArchive::fromJson;
      case PMTILES -> ReadablePmtiles::newReadFromFile;
      case PROTO, PBF -> InMemoryStreamArchive::fromProtobuf;
      case FILES -> p -> ReadableFilesArchive.newReader(p, Arguments.of());
    };


    Files.copy(originalOsm, tempOsm);
    Planetiler.create(Arguments.fromArgs(
      ("--tmpdir=" + tempDir.resolve("data") + " " + args).split("\\s+")
    ))
      .setProfile(new Profile.NullProfile() {
        @Override
        public void processFeature(SourceFeature source, FeatureCollector features) {
          if (source.canBePolygon() && source.hasTag("building", "yes")) {
            features.polygon("building").setZoomRange(0, 14).setMinPixelSize(1);
          } else if (source.isPoint() && source.hasTag("place")) {
            features.point("place").setZoomRange(0, 14);
          }
        }
      })
      .addOsmSource("osm", tempOsm)
      .addNaturalEarthSource("ne", TestUtils.pathToResource("natural_earth_vector.sqlite"))
      .addShapefileSource("shapefile", TestUtils.pathToResource("shapefile.zip"))
      .addGeoPackageSource("geopackage", TestUtils.pathToResource("geopackage.gpkg.zip"), null)
      .addGeoJsonSource("geojson", TestUtils.pathToResource("featurecollection.geojson"), null)
      .setOutput(outputUri)
      .run();

    // make sure it got deleted after write
    if (args.contains("free-osm-after-read")) {
      assertFalse(Files.exists(tempOsm));
    }

    try (var db = readableTileArchiveFactory.create(outputPath)) {
      int features = 0;
      var tileMap = TestUtils.getTileMap(db, tileCompression);
      for (var tile : tileMap.values()) {
        for (var feature : tile) {
          feature.geometry().validate();
          features++;
        }
      }

      int expectedFeatures = args.contains("max-point-buffer=1") ? 2311 : 2313;

      assertEquals(22, tileMap.size(), "num tiles");
      assertEquals(expectedFeatures, features, "num feature");

      final boolean checkMetadata = switch (format) {
        case MBTILES -> true;
        case PMTILES -> true;
        default -> db.metadata() != null;
      };

      if (checkMetadata) {
        assertSubmap(Map.of(
          "planetiler:version", BuildInfo.get().version(),
          "planetiler:osm:osmosisreplicationtime", "2021-04-21T20:21:46Z",
          "planetiler:osm:osmosisreplicationseq", "2947",
          "planetiler:osm:osmosisreplicationurl", "http://download.geofabrik.de/europe/monaco-updates"
        ), db.metadata().toMap());
      }
    }

    final Path layerstats = outputPath.resolveSibling(outputPath.getFileName().toString() + ".layerstats.tsv.gz");
    if (args.contains("--output-layerstats")) {
      assertTrue(Files.exists(layerstats));
      byte[] data = Files.readAllBytes(layerstats);
      byte[] uncompressed = Gzip.gunzip(data);
      String[] lines = new String(uncompressed, StandardCharsets.UTF_8).split("\n");
      assertEquals(33, lines.length);

      assertEquals(List.of(
        "z",
        "x",
        "y",
        "hilbert",
        "archived_tile_bytes",
        "layer",
        "layer_bytes",
        "layer_features",
        "layer_geometries",
        "layer_attr_bytes",
        "layer_attr_keys",
        "layer_attr_values"
      ), List.of(lines[0].split("\t")), lines[0]);

      var mapper = new CsvMapper();
      var reader = mapper
        .readerFor(Map.class)
        .with(CsvSchema.emptySchema().withColumnSeparator('\t').withLineSeparator("\n").withHeader());
      try (var items = reader.readValues(uncompressed)) {
        while (items.hasNext()) {
          @SuppressWarnings("unchecked") Map<String, String> next = (Map<String, String>) items.next();
          int z = Integer.parseInt(next.get("z"));
          int x = Integer.parseInt(next.get("x"));
          int y = Integer.parseInt(next.get("y"));
          int hilbert = Integer.parseInt(next.get("hilbert"));
          assertEquals(hilbert, TileCoord.ofXYZ(x, y, z).hilbertEncoded());
          assertTrue(Integer.parseInt(next.get("z")) <= 14, "bad z: " + next);
        }
      }

      // ensure tilestats standalone executable produces same output
      var standaloneLayerstatsOutput = tempDir.resolve("layerstats2.tsv.gz");
      TileSizeStats.main("--input=" + outputPath, "--output=" + standaloneLayerstatsOutput);
      byte[] standaloneData = Files.readAllBytes(standaloneLayerstatsOutput);
      byte[] standaloneUncompressed = Gzip.gunzip(standaloneData);
      assertEquals(
        new String(uncompressed, StandardCharsets.UTF_8),
        new String(standaloneUncompressed, StandardCharsets.UTF_8)
      );
    } else {
      assertFalse(Files.exists(layerstats));
    }
  }
In-memory tests with fake data and profiles to ensure all features work end-to-end.
planetiler-core/src/test/java/com/onthegomap/planetiler/PlanetilerTests.java