diff --git a/.github/workflows/gem-install.yml b/.github/workflows/gem-install.yml index 55c9432..ead6118 100644 --- a/.github/workflows/gem-install.yml +++ b/.github/workflows/gem-install.yml @@ -84,20 +84,6 @@ jobs: # litestream version # " - darwin-x86_64-install: - needs: ["package"] - runs-on: macos-13 - steps: - - uses: ruby/setup-ruby@v1 - with: - ruby-version: "3.2" - - uses: actions/download-artifact@v4 - with: - name: gem-x86_64-darwin - path: pkg - - run: "gem install pkg/litestream-*.gem" - - run: "litestream version" - darwin-arm64-install: needs: ["package"] runs-on: macos-14 diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b61a0f..91ab929 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ ## [Unreleased] +## [0.15.0] - 2026-02-25 + +### Major Changes + +- **Bump to Litestream 0.5.9**: Replaced `wal` command with `ltx` command (Litestream 0.5.x changed WAL terminology to LTX) +- **Updated configuration format**: Config template now uses Litestream's new `globals` and `unique replica` format +- **New IPC-based dashboard**: Dashboard now uses Litestream's native IPC socket (`/info` and `/list` endpoints) instead of parsing CLI output + +### Deprecations + +- **Removed `generations` command**: Deprecated in Litestream 0.5.x, now removed +- **Removed `snapshots` command**: Deprecated in Litestream 0.5.x, now removed + ## [0.14.0] - 2025-06-14 - Change async behaviour of replicate and other commands ([@hschne](https://github.com/fractaledmind/litestream-ruby/pull/62)) diff --git a/Gemfile.lock b/Gemfile.lock index 51f11ba..0d8436c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - litestream (0.14.0) + litestream (0.15.0) actionpack (>= 7.0) actionview (>= 7.0) activejob (>= 7.0) diff --git a/README.md b/README.md index e5c3056..12426ff 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,9 @@ [Litestream](https://litestream.io/) is a standalone streaming replication tool for SQLite. This gem provides a Ruby interface to Litestream. +> [!WARNING] +> This is the README for versions >= 0.15 which uses [Litestream 0.5.x](https://litestream.io), it introduces breaking changes because of how the Litestream now handles its replicate process. If you use an older version please read the [Litestream migration guide](https://litestream.io/docs/migration/). **TL;DR** you have to update your `config/litestream.yml` file, and `generations` / `snapshots` are replaced with `ltx` so the corresponding commands are no longer available. + ## Installation Install the gem and add to the application's Gemfile by executing: @@ -85,14 +88,17 @@ The gem streamlines the configuration process by providing a default configurati The default configuration file looks like this if you only have one SQLite database: ```yaml +access-key-id: $LITESTREAM_ACCESS_KEY_ID +secret-access-key: $LITESTREAM_SECRET_ACCESS_KEY +region: $LITESTREAM_REGION +endpoint: $LITESTREAM_ENDPOINT + dbs: - path: storage/production.sqlite3 - replicas: - - type: s3 - path: storage/production.sqlite3 - bucket: $LITESTREAM_REPLICA_BUCKET - access-key-id: $LITESTREAM_ACCESS_KEY_ID - secret-access-key: $LITESTREAM_SECRET_ACCESS_KEY + replica: + type: s3 + path: storage/production.sqlite3 + bucket: $LITESTREAM_REPLICA_BUCKET ``` This is the default for Amazon S3. The full range of possible replica types (e.g. other S3-compatible object storage servers) are covered in Litestream's [replica guides](https://litestream.io/guides/#replica-guides). @@ -391,39 +397,13 @@ path replicas /Users/you/Code/your-app/storage/production.sqlite3 s3 ``` -You can also list the generations of a specific database: - -```shell -bin/rails litestream:generations -- --database=storage/production.sqlite3 -``` - -This will list all generations for the specified database, including stats about their lag behind the primary database and the time range they cover: - -``` -name generation lag start end -s3 a295b16a796689f3 -156ms 2024-04-17T00:01:19Z 2024-04-17T00:01:19Z -``` - -You can list the snapshots available for a database: - -```shell -bin/rails litestream:snapshots -- --database=storage/production.sqlite3 -``` - -This command lists snapshots available for that specified database: - -``` -replica generation index size created -s3 a295b16a796689f3 1 4645465 2024-04-17T00:01:19Z -``` - -Finally, you can list the wal files available for a database: +Finally, you can list the ltx files available for a database: ```shell -bin/rails litestream:wal -- --database=storage/production.sqlite3 +bin/rails litestream:ltx -- --database=storage/production.sqlite3 ``` -This command lists wal files available for that specified database: +This command lists ltx files available for that specified database: ``` replica generation index offset size created @@ -441,24 +421,10 @@ Litestream::Commands.databases # => [{"path"=>"/Users/you/Code/your-app/storage/production.sqlite3", "replicas"=>"s3"}] ``` -The `Litestream::Commands.generations` method returns an array of hashes with the "name", "generation", "lag", "start", and "end" keys for each generation: - -```ruby -Litestream::Commands.generations('storage/production.sqlite3') -# => [{"name"=>"s3", "generation"=>"5f4341bc3d22d615", "lag"=>"3s", "start"=>"2024-04-17T19:48:09Z", "end"=>"2024-04-17T19:48:09Z"}] -``` - -The `Litestream::Commands.snapshots` method returns an array of hashes with the "replica", "generation", "index", "size", and "created" keys for each snapshot: - -```ruby -Litestream::Commands.snapshots('storage/production.sqlite3') -# => [{"replica"=>"s3", "generation"=>"5f4341bc3d22d615", "index"=>"0", "size"=>"4645465", "created"=>"2024-04-17T19:48:09Z"}] -``` - -The `Litestream::Commands.wal` method returns an array of hashes with the "replica", "generation", "index", "offset","size", and "created" keys for each wal: +The `Litestream::Commands.ltx` method returns an array of hashes with the "replica", "generation", "index", "offset","size", and "created" keys for each ltx: ```ruby -Litestream::Commands.wal('storage/production.sqlite3') +Litestream::Commands.ltx('storage/production.sqlite3') # => [{"replica"=>"s3", "generation"=>"5f4341bc3d22d615", "index"=>"0", "offset"=>"0", "size"=>"2036", "created"=>"2024-04-17T19:48:09Z"}] ``` @@ -479,12 +445,10 @@ The full set of commands available to the `litestream` executable are covered in ```shell litestream databases [arguments] -litestream generations [arguments] DB_PATH|REPLICA_URL litestream replicate [arguments] litestream restore [arguments] DB_PATH|REPLICA_URL -litestream snapshots [arguments] DB_PATH|REPLICA_URL litestream version -litestream wal [arguments] DB_PATH|REPLICA_URL +litestream ltx [arguments] DB_PATH|REPLICA_URL ``` ### Using in development diff --git a/app/views/litestream/processes/show.html.erb b/app/views/litestream/processes/show.html.erb index d8c8e31..cc93172 100644 --- a/app/views/litestream/processes/show.html.erb +++ b/app/views/litestream/processes/show.html.erb @@ -55,65 +55,72 @@ <%= button_to "Restore", restorations_path, class: "rounded-md bg-slate-800 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-slate-700", params: { database: database['path'] } %> -
-
- <% database['generations'].each do |generation| %> -
- - <%= generation['generation'] %> - (<%= generation['lag'] %> lag) - +
+
Status
+
<%= database['status'] %>
-
-
Start
-
- - - -
+
Last sync
+
+ <% if database['last_sync_at'] %> + + + + <% else %> + Never + <% end %> +
+
+ +
+
+
+ + LTX Files (<%= Array(database['ltx']).size %> files) + -
End
+
+
+
LTX Files
- - - -
+ + + + + + + + + + -
-
Snapshots
-
-
LevelMin TXIDMax TXIDCreated atSize
- - - - - + + <% database['ltx'].each do |ltx| %> + + + + + + - - - - <% generation['snapshots'].each do |snapshot| %> - - - - - - <% end %> - -
Created atIndexSize
+ <%= ltx['level'] %> + + <%= ltx['min_txid'] %> + + <%= ltx['max_txid'] %> + + + + + + <%= number_to_human_size ltx['size'] %> +
- - - - - <%= snapshot['index'] %> - - <%= number_to_human_size snapshot['size'] %> -
- -
-
-
- <% end %> + <% end %> + + + + +
+
<% end %> diff --git a/images/show-screenshot.png b/images/show-screenshot.png index 4a6350c..d8bd3b8 100644 Binary files a/images/show-screenshot.png and b/images/show-screenshot.png differ diff --git a/lib/litestream.rb b/lib/litestream.rb index 159faa9..42792fc 100644 --- a/lib/litestream.rb +++ b/lib/litestream.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require "sqlite3" +require "yaml" module Litestream VerificationFailure = Class.new(StandardError) @@ -28,12 +29,10 @@ def self.configure class Configuration attr_accessor :replica_bucket, :replica_key_id, :replica_access_key - - def initialize - end end - mattr_writer :username, :password, :queue, :replica_bucket, :replica_region, :replica_endpoint, :replica_key_id, :replica_access_key, :systemctl_command, :config_path + mattr_writer :username, :password, :queue, :replica_bucket, :replica_region, :replica_endpoint, :replica_key_id, + :replica_access_key, :systemctl_command, :config_path, :socket mattr_accessor :base_controller_class, default: "::ApplicationController" class << self @@ -102,96 +101,62 @@ def config_path @@config_path || Rails.root.join("config", "litestream.yml") end - def replicate_process - systemctl_info || process_info || {} + def socket + @@socket || read_socket_from_config end - def databases - databases = Commands.databases - - databases.each do |db| - generations = Commands.generations(db["path"]) - snapshots = Commands.snapshots(db["path"]) - db["path"] = db["path"].gsub(Rails.root.to_s, "[ROOT]") - - db["generations"] = generations.map do |generation| - id = generation["generation"] - replica = generation["name"] - generation["snapshots"] = snapshots.select { |snapshot| snapshot["generation"] == id && snapshot["replica"] == replica } - .map { |s| s.slice("index", "size", "created") } - generation.slice("generation", "name", "lag", "start", "end", "snapshots") - end + def read_socket_from_config + default = "/var/run/litestream.sock" + + unless File.exist?(config_path) + warn "[Litestream] Config file not found: #{config_path}, using default: #{default}" + return default end - end - private - - def systemctl_info - return if `which systemctl`.empty? - - systemctl_output = `#{Litestream.systemctl_command}` - systemctl_exit_code = $?.exitstatus - return unless systemctl_exit_code.zero? - - # ["● litestream.service - Litestream", - # " Loaded: loaded (/lib/systemd/system/litestream.service; enabled; vendor preset: enabled)", - # " Active: active (running) since Tue 2023-07-25 13:49:43 UTC; 8 months 24 days ago", - # " Main PID: 1179656 (litestream)", - # " Tasks: 9 (limit: 1115)", - # " Memory: 22.9M", - # " CPU: 10h 49.843s", - # " CGroup: /system.slice/litestream.service", - # " └─1179656 /usr/bin/litestream replicate", - # "", - # "Warning: some journal files were not opened due to insufficient permissions."] - - info = {} - systemctl_output.chomp.split("\n").each do |line| - line.strip! - if line.start_with?("Main PID:") - _key, value = line.split(":") - pid, _name = value.strip.split(" ") - info[:pid] = pid - elsif line.start_with?("Active:") - value, _ago = line.split(";") - status, timestamp = value.split(" since ") - info[:started] = DateTime.strptime(timestamp.strip, "%a %Y-%m-%d %H:%M:%S %Z") - status_match = status.match(%r{\((?.*)\)}) - info[:status] = status_match ? status_match[:status] : nil - end + config = YAML.safe_load_file(config_path) + unless config + warn "[Litestream] Config file is empty, using default: #{default}" + return default end - info - end - - def process_info - litestream_replicate_ps = `ps -ax | grep litestream | grep replicate` - exit_code = $?.exitstatus - return unless exit_code.zero? - - info = {} - litestream_replicate_ps.chomp.split("\n").each do |line| - next unless line.include?("litestream replicate") - - pid, * = line.split(" ") - info[:pid] = pid - state, _, lstart = `ps -o "state,lstart" #{pid}`.chomp.split("\n").last.partition(/\s+/) - - info[:status] = case state[0] - when "I" then "idle" - when "R" then "running" - when "S" then "sleeping" - when "T" then "stopped" - when "U" then "uninterruptible" - when "Z" then "zombie" - end - info[:started] = DateTime.strptime(lstart.strip, "%a %b %d %H:%M:%S %Y") + + socket_path = config.dig("socket", "path") + socket_path || default + rescue Errno::ENOENT, Psych::SyntaxError => e + warn "[Litestream] Warning: Could not read socket path from config: #{e.message}" + "/var/run/litestream.sock" + end + + def replicate_process + info = IPC.info(socket) + { + pid: info["pid"], + status: "running", + started: DateTime.parse(info["started_at"]) + } + rescue => e + warn "[Litestream] Warning: Could not retrieve replicate process info via IPC: #{e.class}: #{e.message}" + { + pid: nil, + status: "unavailable", + started: nil + } + end + + def databases + list = IPC.list(socket) || {} + databases = list["databases"] || [] + databases.map do |db| + db.merge("ltx" => Commands.ltx(db["path"], "-level" => "all")) end - info + rescue => e + warn "[Litestream] Warning: Could not retrieve databases info via IPC: #{e.class}: #{e.message}" + [] end end end require_relative "litestream/version" +require_relative "litestream/ipc" require_relative "litestream/upstream" require_relative "litestream/commands" require_relative "litestream/engine" if defined?(::Rails::Engine) diff --git a/lib/litestream/commands.rb b/lib/litestream/commands.rb index 0d86aad..f2a9d98 100644 --- a/lib/litestream/commands.rb +++ b/lib/litestream/commands.rb @@ -114,22 +114,10 @@ def databases(**argv) execute("databases", argv) end - def generations(database, **argv) - raise DatabaseRequiredException, "database argument is required for generations command, e.g. litestream:generations -- --database=path/to/database.sqlite" if database.nil? + def ltx(database, **argv) + raise DatabaseRequiredException, "database argument is required for ltx command, e.g. litestream:ltx -- --database=path/to/database.sqlite" if database.nil? - execute("generations", argv, database) - end - - def snapshots(database, **argv) - raise DatabaseRequiredException, "database argument is required for snapshots command, e.g. litestream:snapshots -- --database=path/to/database.sqlite" if database.nil? - - execute("snapshots", argv, database) - end - - def wal(database, **argv) - raise DatabaseRequiredException, "database argument is required for wal command, e.g. litestream:wal -- --database=path/to/database.sqlite" if database.nil? - - execute("wal", argv, database) + execute("ltx", argv, database) end private diff --git a/lib/litestream/generators/litestream/templates/config.yml.erb b/lib/litestream/generators/litestream/templates/config.yml.erb index 43009db..040d9dc 100644 --- a/lib/litestream/generators/litestream/templates/config.yml.erb +++ b/lib/litestream/generators/litestream/templates/config.yml.erb @@ -9,13 +9,25 @@ # `replicate` command. # # For more details, see: https://litestream.io/reference/config/ + +# Global defaults inherited by all replicas +access-key-id: $LITESTREAM_ACCESS_KEY_ID +secret-access-key: $LITESTREAM_SECRET_ACCESS_KEY +region: $LITESTREAM_REGION +endpoint: $LITESTREAM_ENDPOINT + +# Socket configuration for litestream's API. This is used by the litestream-ruby gem to communicate with the litestream process. +# By default, this is set to use a Unix socket at /var/run/litestream.sock, but you can customize this as needed (e.g. /tmp/litestream.sock on MacOS). +# see https://litestream.io/reference/ipc/ +socket: + enabled: true +# path: /tmp/litestream.sock + dbs: <%- production_sqlite_databases.each do |database| -%> - path: <%= database %> - replicas: - - type: s3 - bucket: $LITESTREAM_REPLICA_BUCKET - path: <%= database %> - access-key-id: $LITESTREAM_ACCESS_KEY_ID - secret-access-key: $LITESTREAM_SECRET_ACCESS_KEY + replica: + type: s3 + bucket: $LITESTREAM_REPLICA_BUCKET + path: <%= database %> <%- end -%> diff --git a/lib/litestream/ipc.rb b/lib/litestream/ipc.rb new file mode 100644 index 0000000..a321133 --- /dev/null +++ b/lib/litestream/ipc.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require "json" +require "socket" + +module Litestream + class IPC + class ConnectionError < StandardError + end + + class << self + def info(socket_path) + request("/info", socket_path) + end + + def list(socket_path) + request("/list", socket_path) + end + + private + + def request(path, socket_path) + unless File.exist?(socket_path) + raise ConnectionError, "Litestream IPC socket not found at #{socket_path}. Is the litestream daemon running?" + end + + socket = nil + begin + socket = UNIXSocket.new(socket_path) + socket.write("GET #{path} HTTP/1.0\r\nHost: localhost\r\n\r\n") + response = socket.read + ensure + socket.close if socket && !socket.closed? + end + + headers, body = response.split("\r\n\r\n", 2) + status_code = headers.lines.first[/\d{3}/].to_i + + unless (200..299).cover?(status_code) + raise ConnectionError, "Failed to connect to Litestream IPC socket at #{socket_path}: HTTP #{status_code}" + end + + JSON.parse(body) + rescue Errno::ENOENT, Errno::ECONNREFUSED, Errno::EPIPE, Errno::ECONNRESET => e + raise ConnectionError, "Failed to connect to Litestream IPC socket at #{socket_path}: #{e.message}" + rescue JSON::ParserError => e + raise ConnectionError, "Failed to parse IPC response from #{socket_path}: #{e.message}" + end + end + end +end diff --git a/lib/litestream/upstream.rb b/lib/litestream/upstream.rb index 0029efd..5d177ac 100644 --- a/lib/litestream/upstream.rb +++ b/lib/litestream/upstream.rb @@ -1,14 +1,14 @@ module Litestream module Upstream - VERSION = "v0.3.13" + VERSION = "0.5.9" # rubygems platform name => upstream release filename NATIVE_PLATFORMS = { "aarch64-linux" => "litestream-#{VERSION}-linux-arm64.tar.gz", - "arm64-darwin" => "litestream-#{VERSION}-darwin-arm64.zip", + "arm64-darwin" => "litestream-#{VERSION}-darwin-arm64.tar.gz", "arm64-linux" => "litestream-#{VERSION}-linux-arm64.tar.gz", - "x86_64-darwin" => "litestream-#{VERSION}-darwin-amd64.zip", - "x86_64-linux" => "litestream-#{VERSION}-linux-amd64.tar.gz" + "x86_64-darwin" => "litestream-#{VERSION}-darwin-x86_64.tar.gz", + "x86_64-linux" => "litestream-#{VERSION}-linux-x86_64.tar.gz" } end end diff --git a/lib/litestream/version.rb b/lib/litestream/version.rb index df8a12c..e203145 100644 --- a/lib/litestream/version.rb +++ b/lib/litestream/version.rb @@ -1,3 +1,3 @@ module Litestream - VERSION = "0.14.0" + VERSION = "0.15.0" end diff --git a/lib/tasks/litestream_tasks.rake b/lib/tasks/litestream_tasks.rake index 387701b..a82e209 100644 --- a/lib/tasks/litestream_tasks.rake +++ b/lib/tasks/litestream_tasks.rake @@ -32,29 +32,13 @@ namespace :litestream do puts Litestream::Commands::Output.format(Litestream::Commands.databases(**options)) end - desc "List all generations for a database or replica, for example `rake litestream:generations -- -database=storage/production.sqlite3`" - task generations: :environment do - options = parse_argv_options - database = options.delete(:"--database") || options.delete(:"-database") - - puts Litestream::Commands::Output.format(Litestream::Commands.generations(database, **options)) - end - - desc "List all snapshots for a database or replica, for example `rake litestream:snapshots -- -database=storage/production.sqlite3`" - task snapshots: :environment do - options = parse_argv_options - database = options.delete(:"--database") || options.delete(:"-database") - - puts Litestream::Commands::Output.format(Litestream::Commands.snapshots(database, **options)) - end - - desc "List all wal files for a database or replica, for example `rake litestream:wal -- -database=storage/production.sqlite3`" - task wal: :environment do + desc "List all ltx files for a database or replica, for example `rake litestream:ltx -- -database=storage/production.sqlite3`" + task ltx: :environment do options = parse_argv_options database = options.delete(:"--database") || options.delete(:"-database") puts Litestream::Commands::Output.format( - Litestream::Commands.wal(database, **options) + Litestream::Commands.ltx(database, **options) ) end diff --git a/rakelib/package.rake b/rakelib/package.rake index f1a047f..4df43bb 100644 --- a/rakelib/package.rake +++ b/rakelib/package.rake @@ -63,7 +63,7 @@ require "zip" require_relative "../lib/litestream/upstream" def litestream_download_url(filename) - "https://github.com/benbjohnson/litestream/releases/download/#{Litestream::Upstream::VERSION}/#{filename}" + "https://github.com/benbjohnson/litestream/releases/download/v#{Litestream::Upstream::VERSION}/#{filename}" end LITESTREAM_RAILS_GEMSPEC = Bundler.load_gemspec("litestream.gemspec") diff --git a/test/controllers/test_processes_controller.rb b/test/controllers/test_processes_controller.rb index 3f15a6e..47c890a 100644 --- a/test/controllers/test_processes_controller.rb +++ b/test/controllers/test_processes_controller.rb @@ -5,16 +5,11 @@ class Litestream::TestProcessesController < ActionDispatch::IntegrationTest stubbed_process = {pid: "12345", status: "sleeping", started: DateTime.now} stubbed_databases = [ {"path" => "[ROOT]/storage/test.sqlite3", - "replicas" => "s3", - "generations" => [ - {"generation" => SecureRandom.hex, - "name" => "s3", - "lag" => "23h59m59s", - "start" => "2024-05-02T11:32:16Z", - "end" => "2024-05-02T11:33:10Z", - "snapshots" => [ - {"index" => "0", "size" => "4145735", "created" => "2024-05-02T11:32:16Z"} - ]} + "status" => "active", + "last_sync_at" => "2026-02-25T10:00:00Z", + "ltx" => [ + {"min_txid" => "0000000000000001", "max_txid" => "0000000000000010", "size" => 4096, + "created" => "2026-02-25T10:00:00Z", "level" => "0"} ]} ] Litestream.stub :replicate_process, stubbed_process do @@ -30,7 +25,6 @@ class Litestream::TestProcessesController < ActionDispatch::IntegrationTest assert_select "#databases li", 1 do assert_select "h2 code", stubbed_databases[0]["path"] - assert_select "details##{stubbed_databases[0]["generations"][0]["generation"]}" end end end diff --git a/test/litestream/test_commands.rb b/test/litestream/test_commands.rb index 9b96224..77456f2 100644 --- a/test/litestream/test_commands.rb +++ b/test/litestream/test_commands.rb @@ -441,27 +441,27 @@ def test_databases_read_from_custom_configured_litestream_config_path end end - class TestGenerationsCommand < TestCommands - def test_generations_with_no_options + class TestLtxCommand < TestCommands + def test_ltx_with_no_options stub = proc do |cmd| executable, command, *argv = cmd assert_match Regexp.new("exe/test/litestream"), executable - assert_equal "generations", command + assert_equal "ltx", command assert_equal 3, argv.size assert_equal "--config", argv[0] assert_match Regexp.new("dummy/config/litestream.yml"), argv[1] assert_equal "db/test.sqlite3", argv[2] end Litestream::Commands.stub :run, stub do - Litestream::Commands.generations("db/test.sqlite3") + Litestream::Commands.ltx("db/test.sqlite3") end end - def test_generations_with_boolean_option + def test_ltx_with_boolean_option stub = proc do |cmd| executable, command, *argv = cmd assert_match Regexp.new("exe/test/litestream"), executable - assert_equal "generations", command + assert_equal "ltx", command assert_equal 4, argv.size assert_equal "--config", argv[0] assert_match Regexp.new("dummy/config/litestream.yml"), argv[1] @@ -469,15 +469,15 @@ def test_generations_with_boolean_option assert_equal "db/test.sqlite3", argv[3] end Litestream::Commands.stub :run, stub do - Litestream::Commands.generations("db/test.sqlite3", "--if-db-not-exists" => nil) + Litestream::Commands.ltx("db/test.sqlite3", "--if-db-not-exists" => nil) end end - def test_generations_with_string_option + def test_ltx_with_string_option stub = proc do |cmd| executable, command, *argv = cmd assert_match Regexp.new("exe/test/litestream"), executable - assert_equal "generations", command + assert_equal "ltx", command assert_equal 5, argv.size assert_equal "--config", argv[0] assert_match Regexp.new("dummy/config/litestream.yml"), argv[1] @@ -486,30 +486,30 @@ def test_generations_with_string_option assert_equal "db/test.sqlite3", argv[4] end Litestream::Commands.stub :run, stub do - Litestream::Commands.generations("db/test.sqlite3", "--parallelism" => 10) + Litestream::Commands.ltx("db/test.sqlite3", "--parallelism" => 10) end end - def test_generations_with_config_option + def test_ltx_with_config_option stub = proc do |cmd| executable, command, *argv = cmd assert_match Regexp.new("exe/test/litestream"), executable - assert_equal "generations", command + assert_equal "ltx", command assert_equal 3, argv.size assert_equal "--config", argv[0] assert_equal "CONFIG", argv[1] assert_equal "db/test.sqlite3", argv[2] end Litestream::Commands.stub :run, stub do - Litestream::Commands.generations("db/test.sqlite3", "--config" => "CONFIG") + Litestream::Commands.ltx("db/test.sqlite3", "--config" => "CONFIG") end end - def test_generations_sets_replica_bucket_env_var_from_config_when_env_var_not_set + def test_ltx_sets_replica_bucket_env_var_from_config_when_env_var_not_set Litestream.replica_bucket = "mybkt" Litestream::Commands.stub :run, nil do - Litestream::Commands.generations("db/test.sqlite3") + Litestream::Commands.ltx("db/test.sqlite3") end assert_equal "mybkt", ENV["LITESTREAM_REPLICA_BUCKET"] @@ -517,11 +517,11 @@ def test_generations_sets_replica_bucket_env_var_from_config_when_env_var_not_se assert_nil ENV["LITESTREAM_SECRET_ACCESS_KEY"] end - def test_generations_sets_replica_key_id_env_var_from_config_when_env_var_not_set + def test_ltx_sets_replica_key_id_env_var_from_config_when_env_var_not_set Litestream.replica_key_id = "mykey" Litestream::Commands.stub :run, nil do - Litestream::Commands.generations("db/test.sqlite3") + Litestream::Commands.ltx("db/test.sqlite3") end assert_nil ENV["LITESTREAM_REPLICA_BUCKET"] @@ -529,11 +529,11 @@ def test_generations_sets_replica_key_id_env_var_from_config_when_env_var_not_se assert_nil ENV["LITESTREAM_SECRET_ACCESS_KEY"] end - def test_generations_sets_replica_access_key_env_var_from_config_when_env_var_not_set + def test_ltx_sets_replica_access_key_env_var_from_config_when_env_var_not_set Litestream.replica_access_key = "access" Litestream::Commands.stub :run, nil do - Litestream::Commands.generations("db/test.sqlite3") + Litestream::Commands.ltx("db/test.sqlite3") end assert_nil ENV["LITESTREAM_REPLICA_BUCKET"] @@ -541,13 +541,13 @@ def test_generations_sets_replica_access_key_env_var_from_config_when_env_var_no assert_equal "access", ENV["LITESTREAM_SECRET_ACCESS_KEY"] end - def test_generations_sets_all_env_vars_from_config_when_env_vars_not_set + def test_ltx_sets_all_env_vars_from_config_when_env_vars_not_set Litestream.replica_bucket = "mybkt" Litestream.replica_key_id = "mykey" Litestream.replica_access_key = "access" Litestream::Commands.stub :run, nil do - Litestream::Commands.generations("db/test.sqlite3") + Litestream::Commands.ltx("db/test.sqlite3") end assert_equal "mybkt", ENV["LITESTREAM_REPLICA_BUCKET"] @@ -555,7 +555,7 @@ def test_generations_sets_all_env_vars_from_config_when_env_vars_not_set assert_equal "access", ENV["LITESTREAM_SECRET_ACCESS_KEY"] end - def test_generations_does_not_set_env_var_from_config_when_env_vars_already_set + def test_ltx_does_not_set_env_var_from_config_when_env_vars_already_set ENV["LITESTREAM_REPLICA_BUCKET"] = "original_bkt" ENV["LITESTREAM_ACCESS_KEY_ID"] = "original_key" ENV["LITESTREAM_SECRET_ACCESS_KEY"] = "original_access" @@ -565,273 +565,7 @@ def test_generations_does_not_set_env_var_from_config_when_env_vars_already_set Litestream.replica_access_key = "access" Litestream::Commands.stub :run, nil do - Litestream::Commands.generations("db/test.sqlite3") - end - - assert_equal "original_bkt", ENV["LITESTREAM_REPLICA_BUCKET"] - assert_equal "original_key", ENV["LITESTREAM_ACCESS_KEY_ID"] - assert_equal "original_access", ENV["LITESTREAM_SECRET_ACCESS_KEY"] - end - end - - class TestSnapshotsCommand < TestCommands - def test_snapshots_with_no_options - stub = proc do |cmd| - executable, command, *argv = cmd - assert_match Regexp.new("exe/test/litestream"), executable - assert_equal "snapshots", command - assert_equal 3, argv.size - assert_equal "--config", argv[0] - assert_match Regexp.new("dummy/config/litestream.yml"), argv[1] - assert_equal "db/test.sqlite3", argv[2] - end - Litestream::Commands.stub :run, stub do - Litestream::Commands.snapshots("db/test.sqlite3") - end - end - - def test_snapshots_with_boolean_option - stub = proc do |cmd| - executable, command, *argv = cmd - assert_match Regexp.new("exe/test/litestream"), executable - assert_equal "snapshots", command - assert_equal 4, argv.size - assert_equal "--config", argv[0] - assert_match Regexp.new("dummy/config/litestream.yml"), argv[1] - assert_equal "--if-db-not-exists", argv[2] - assert_equal "db/test.sqlite3", argv[3] - end - Litestream::Commands.stub :run, stub do - Litestream::Commands.snapshots("db/test.sqlite3", "--if-db-not-exists" => nil) - end - end - - def test_snapshots_with_string_option - stub = proc do |cmd| - executable, command, *argv = cmd - assert_match Regexp.new("exe/test/litestream"), executable - assert_equal "snapshots", command - assert_equal 5, argv.size - assert_equal "--config", argv[0] - assert_match Regexp.new("dummy/config/litestream.yml"), argv[1] - assert_equal "--parallelism", argv[2] - assert_equal 10, argv[3] - assert_equal "db/test.sqlite3", argv[4] - end - Litestream::Commands.stub :run, stub do - Litestream::Commands.snapshots("db/test.sqlite3", "--parallelism" => 10) - end - end - - def test_snapshots_with_config_option - stub = proc do |cmd| - executable, command, *argv = cmd - assert_match Regexp.new("exe/test/litestream"), executable - assert_equal "snapshots", command - assert_equal 3, argv.size - assert_equal "--config", argv[0] - assert_equal "CONFIG", argv[1] - assert_equal "db/test.sqlite3", argv[2] - end - Litestream::Commands.stub :run, stub do - Litestream::Commands.snapshots("db/test.sqlite3", "--config" => "CONFIG") - end - end - - def test_snapshots_sets_replica_bucket_env_var_from_config_when_env_var_not_set - Litestream.replica_bucket = "mybkt" - - Litestream::Commands.stub :run, nil do - Litestream::Commands.snapshots("db/test.sqlite3") - end - - assert_equal "mybkt", ENV["LITESTREAM_REPLICA_BUCKET"] - assert_nil ENV["LITESTREAM_ACCESS_KEY_ID"] - assert_nil ENV["LITESTREAM_SECRET_ACCESS_KEY"] - end - - def test_snapshots_sets_replica_key_id_env_var_from_config_when_env_var_not_set - Litestream.replica_key_id = "mykey" - - Litestream::Commands.stub :run, nil do - Litestream::Commands.snapshots("db/test.sqlite3") - end - - assert_nil ENV["LITESTREAM_REPLICA_BUCKET"] - assert_equal "mykey", ENV["LITESTREAM_ACCESS_KEY_ID"] - assert_nil ENV["LITESTREAM_SECRET_ACCESS_KEY"] - end - - def test_snapshots_sets_replica_access_key_env_var_from_config_when_env_var_not_set - Litestream.replica_access_key = "access" - - Litestream::Commands.stub :run, nil do - Litestream::Commands.snapshots("db/test.sqlite3") - end - - assert_nil ENV["LITESTREAM_REPLICA_BUCKET"] - assert_nil ENV["LITESTREAM_ACCESS_KEY_ID"] - assert_equal "access", ENV["LITESTREAM_SECRET_ACCESS_KEY"] - end - - def test_snapshots_sets_all_env_vars_from_config_when_env_vars_not_set - Litestream.replica_bucket = "mybkt" - Litestream.replica_key_id = "mykey" - Litestream.replica_access_key = "access" - - Litestream::Commands.stub :run, nil do - Litestream::Commands.snapshots("db/test.sqlite3") - end - - assert_equal "mybkt", ENV["LITESTREAM_REPLICA_BUCKET"] - assert_equal "mykey", ENV["LITESTREAM_ACCESS_KEY_ID"] - assert_equal "access", ENV["LITESTREAM_SECRET_ACCESS_KEY"] - end - - def test_snapshots_does_not_set_env_var_from_config_when_env_vars_already_set - ENV["LITESTREAM_REPLICA_BUCKET"] = "original_bkt" - ENV["LITESTREAM_ACCESS_KEY_ID"] = "original_key" - ENV["LITESTREAM_SECRET_ACCESS_KEY"] = "original_access" - - Litestream.replica_bucket = "mybkt" - Litestream.replica_key_id = "mykey" - Litestream.replica_access_key = "access" - - Litestream::Commands.stub :run, nil do - Litestream::Commands.snapshots("db/test.sqlite3") - end - - assert_equal "original_bkt", ENV["LITESTREAM_REPLICA_BUCKET"] - assert_equal "original_key", ENV["LITESTREAM_ACCESS_KEY_ID"] - assert_equal "original_access", ENV["LITESTREAM_SECRET_ACCESS_KEY"] - end - end - - class TestWalCommand < TestCommands - def test_wal_with_no_options - stub = proc do |cmd| - executable, command, *argv = cmd - assert_match Regexp.new("exe/test/litestream"), executable - assert_equal "wal", command - assert_equal 3, argv.size - assert_equal "--config", argv[0] - assert_match Regexp.new("dummy/config/litestream.yml"), argv[1] - assert_equal "db/test.sqlite3", argv[2] - end - Litestream::Commands.stub :run, stub do - Litestream::Commands.wal("db/test.sqlite3") - end - end - - def test_wal_with_boolean_option - stub = proc do |cmd| - executable, command, *argv = cmd - assert_match Regexp.new("exe/test/litestream"), executable - assert_equal "wal", command - assert_equal 4, argv.size - assert_equal "--config", argv[0] - assert_match Regexp.new("dummy/config/litestream.yml"), argv[1] - assert_equal "--if-db-not-exists", argv[2] - assert_equal "db/test.sqlite3", argv[3] - end - Litestream::Commands.stub :run, stub do - Litestream::Commands.wal("db/test.sqlite3", "--if-db-not-exists" => nil) - end - end - - def test_wal_with_string_option - stub = proc do |cmd| - executable, command, *argv = cmd - assert_match Regexp.new("exe/test/litestream"), executable - assert_equal "wal", command - assert_equal 5, argv.size - assert_equal "--config", argv[0] - assert_match Regexp.new("dummy/config/litestream.yml"), argv[1] - assert_equal "--parallelism", argv[2] - assert_equal 10, argv[3] - assert_equal "db/test.sqlite3", argv[4] - end - Litestream::Commands.stub :run, stub do - Litestream::Commands.wal("db/test.sqlite3", "--parallelism" => 10) - end - end - - def test_wal_with_config_option - stub = proc do |cmd| - executable, command, *argv = cmd - assert_match Regexp.new("exe/test/litestream"), executable - assert_equal "wal", command - assert_equal 3, argv.size - assert_equal "--config", argv[0] - assert_equal "CONFIG", argv[1] - assert_equal "db/test.sqlite3", argv[2] - end - Litestream::Commands.stub :run, stub do - Litestream::Commands.wal("db/test.sqlite3", "--config" => "CONFIG") - end - end - - def test_wal_sets_replica_bucket_env_var_from_config_when_env_var_not_set - Litestream.replica_bucket = "mybkt" - - Litestream::Commands.stub :run, nil do - Litestream::Commands.wal("db/test.sqlite3") - end - - assert_equal "mybkt", ENV["LITESTREAM_REPLICA_BUCKET"] - assert_nil ENV["LITESTREAM_ACCESS_KEY_ID"] - assert_nil ENV["LITESTREAM_SECRET_ACCESS_KEY"] - end - - def test_wal_sets_replica_key_id_env_var_from_config_when_env_var_not_set - Litestream.replica_key_id = "mykey" - - Litestream::Commands.stub :run, nil do - Litestream::Commands.wal("db/test.sqlite3") - end - - assert_nil ENV["LITESTREAM_REPLICA_BUCKET"] - assert_equal "mykey", ENV["LITESTREAM_ACCESS_KEY_ID"] - assert_nil ENV["LITESTREAM_SECRET_ACCESS_KEY"] - end - - def test_wal_sets_replica_access_key_env_var_from_config_when_env_var_not_set - Litestream.replica_access_key = "access" - - Litestream::Commands.stub :run, nil do - Litestream::Commands.wal("db/test.sqlite3") - end - - assert_nil ENV["LITESTREAM_REPLICA_BUCKET"] - assert_nil ENV["LITESTREAM_ACCESS_KEY_ID"] - assert_equal "access", ENV["LITESTREAM_SECRET_ACCESS_KEY"] - end - - def test_wal_sets_all_env_vars_from_config_when_env_vars_not_set - Litestream.replica_bucket = "mybkt" - Litestream.replica_key_id = "mykey" - Litestream.replica_access_key = "access" - - Litestream::Commands.stub :run, nil do - Litestream::Commands.wal("db/test.sqlite3") - end - - assert_equal "mybkt", ENV["LITESTREAM_REPLICA_BUCKET"] - assert_equal "mykey", ENV["LITESTREAM_ACCESS_KEY_ID"] - assert_equal "access", ENV["LITESTREAM_SECRET_ACCESS_KEY"] - end - - def test_wal_does_not_set_env_var_from_config_when_env_vars_already_set - ENV["LITESTREAM_REPLICA_BUCKET"] = "original_bkt" - ENV["LITESTREAM_ACCESS_KEY_ID"] = "original_key" - ENV["LITESTREAM_SECRET_ACCESS_KEY"] = "original_access" - - Litestream.replica_bucket = "mybkt" - Litestream.replica_key_id = "mykey" - Litestream.replica_access_key = "access" - - Litestream::Commands.stub :run, nil do - Litestream::Commands.wal("db/test.sqlite3") + Litestream::Commands.ltx("db/test.sqlite3") end assert_equal "original_bkt", ENV["LITESTREAM_REPLICA_BUCKET"] diff --git a/test/tasks/test_litestream_tasks.rb b/test/tasks/test_litestream_tasks.rb index 344c3ec..99348c9 100644 --- a/test/tasks/test_litestream_tasks.rb +++ b/test/tasks/test_litestream_tasks.rb @@ -9,9 +9,7 @@ def setup Rake::Task["litestream:replicate"].reenable Rake::Task["litestream:restore"].reenable Rake::Task["litestream:databases"].reenable - Rake::Task["litestream:generations"].reenable - Rake::Task["litestream:snapshots"].reenable - Rake::Task["litestream:wal"].reenable + Rake::Task["litestream:ltx"].reenable end def teardown @@ -138,127 +136,43 @@ def test_databases_task_with_arguments_without_separator end end - class TestGenerationsTask < TestLitestreamTasks - def test_generations_task_with_only_database_using_single_dash + class TestLtxTask < TestLitestreamTasks + def test_ltx_task_with_only_database_using_single_dash ARGV.replace ["--", "-database=db/test.sqlite3"] fake = Minitest::Mock.new fake.expect :call, nil, ["db/test.sqlite3"] - Litestream::Commands.stub :generations, fake do - Rake.application.invoke_task "litestream:generations" + Litestream::Commands.stub :ltx, fake do + Rake.application.invoke_task "litestream:ltx" end fake.verify end - def test_generations_task_with_only_database_using_double_dash + def test_ltx_task_with_only_database_using_double_dash ARGV.replace ["--", "--database=db/test.sqlite3"] fake = Minitest::Mock.new fake.expect :call, nil, ["db/test.sqlite3"] - Litestream::Commands.stub :generations, fake do - Rake.application.invoke_task "litestream:generations" + Litestream::Commands.stub :ltx, fake do + Rake.application.invoke_task "litestream:ltx" end fake.verify end - def test_generations_task_with_arguments + def test_ltx_task_with_arguments ARGV.replace ["--", "-database=db/test.sqlite3", "--if-db-not-exists"] fake = Minitest::Mock.new fake.expect :call, nil, ["db/test.sqlite3"], "--if-db-not-exists": nil - Litestream::Commands.stub :generations, fake do - Rake.application.invoke_task "litestream:generations" + Litestream::Commands.stub :ltx, fake do + Rake.application.invoke_task "litestream:ltx" end fake.verify end - def test_generations_task_with_arguments_without_separator + def test_ltx_task_with_arguments_without_separator ARGV.replace ["-database=db/test.sqlite3"] fake = Minitest::Mock.new fake.expect :call, nil, [nil] - Litestream::Commands.stub :generations, fake do - Rake.application.invoke_task "litestream:generations" - end - fake.verify - end - end - - class TestSnapshotsTask < TestLitestreamTasks - def test_snapshots_task_with_only_database_using_single_dash - ARGV.replace ["--", "-database=db/test.sqlite3"] - fake = Minitest::Mock.new - fake.expect :call, nil, ["db/test.sqlite3"] - Litestream::Commands.stub :snapshots, fake do - Rake.application.invoke_task "litestream:snapshots" - end - fake.verify - end - - def test_snapshots_task_with_only_database_using_double_dash - ARGV.replace ["--", "--database=db/test.sqlite3"] - fake = Minitest::Mock.new - fake.expect :call, nil, ["db/test.sqlite3"] - Litestream::Commands.stub :snapshots, fake do - Rake.application.invoke_task "litestream:snapshots" - end - fake.verify - end - - def test_snapshots_task_with_arguments - ARGV.replace ["--", "-database=db/test.sqlite3", "--if-db-not-exists"] - fake = Minitest::Mock.new - fake.expect :call, nil, ["db/test.sqlite3"], "--if-db-not-exists": nil - Litestream::Commands.stub :snapshots, fake do - Rake.application.invoke_task "litestream:snapshots" - end - fake.verify - end - - def test_snapshots_task_with_arguments_without_separator - ARGV.replace ["-database=db/test.sqlite3"] - fake = Minitest::Mock.new - fake.expect :call, nil, [nil] - Litestream::Commands.stub :snapshots, fake do - Rake.application.invoke_task "litestream:snapshots" - end - fake.verify - end - end - - class TestWalTask < TestLitestreamTasks - def test_wal_task_with_only_database_using_single_dash - ARGV.replace ["--", "-database=db/test.sqlite3"] - fake = Minitest::Mock.new - fake.expect :call, nil, ["db/test.sqlite3"] - Litestream::Commands.stub :wal, fake do - Rake.application.invoke_task "litestream:wal" - end - fake.verify - end - - def test_wal_task_with_only_database_using_double_dash - ARGV.replace ["--", "--database=db/test.sqlite3"] - fake = Minitest::Mock.new - fake.expect :call, nil, ["db/test.sqlite3"] - Litestream::Commands.stub :wal, fake do - Rake.application.invoke_task "litestream:wal" - end - fake.verify - end - - def test_wal_task_with_arguments - ARGV.replace ["--", "-database=db/test.sqlite3", "--if-db-not-exists"] - fake = Minitest::Mock.new - fake.expect :call, nil, ["db/test.sqlite3"], "--if-db-not-exists": nil - Litestream::Commands.stub :wal, fake do - Rake.application.invoke_task "litestream:wal" - end - fake.verify - end - - def test_wal_task_with_arguments_without_separator - ARGV.replace ["-database=db/test.sqlite3"] - fake = Minitest::Mock.new - fake.expect :call, nil, [nil] - Litestream::Commands.stub :wal, fake do - Rake.application.invoke_task "litestream:wal" + Litestream::Commands.stub :ltx, fake do + Rake.application.invoke_task "litestream:ltx" end fake.verify end diff --git a/test/test_litestream.rb b/test/test_litestream.rb index 5c1f41d..3ac2cd6 100644 --- a/test/test_litestream.rb +++ b/test/test_litestream.rb @@ -5,84 +5,58 @@ class TestLitestream < Minitest::Test def teardown Litestream.systemctl_command = nil + Litestream.socket = nil end def test_that_it_has_a_version_number refute_nil ::Litestream::VERSION end - def test_replicate_process_systemd - stubbed_status = ["● litestream.service - Litestream", - " Loaded: loaded (/lib/systemd/system/litestream.service; enabled; vendor preset: enabled)", - " Active: active (running) since Tue 2023-07-25 13:49:43 UTC; 8 months 24 days ago", - " Main PID: 1179656 (litestream)", - " Tasks: 9 (limit: 1115)", - " Memory: 22.9M", - " CPU: 10h 49.843s", - " CGroup: /system.slice/litestream.service", - " └─1179656 /usr/bin/litestream replicate", - "", - "Warning: some journal files were not opened due to insufficient permissions."].join("\n") - Litestream.stub :`, stubbed_status do + def test_replicate_process + stubbed_info = {"version" => "0.5.9", "pid" => 12_345, "uptime_seconds" => 3600, + "started_at" => "2026-02-25T10:00:00Z"} + Litestream::IPC.stub :info, stubbed_info do info = Litestream.replicate_process assert_equal info[:status], "running" - assert_equal info[:pid], "1179656" + assert_equal info[:pid], 12_345 assert_equal info[:started].class, DateTime end end - def test_replicate_process_systemd_custom_command - stubbed_status = ["● myapp-litestream.service - Litestream", - " Loaded: loaded (/lib/systemd/system/litestream.service; enabled; vendor preset: enabled)", - " Active: active (running) since Tue 2023-07-25 13:49:43 UTC; 8 months 24 days ago", - " Main PID: 1179656 (litestream)", - " Tasks: 9 (limit: 1115)", - " Memory: 22.9M", - " CPU: 10h 49.843s", - " CGroup: /system.slice/litestream.service", - " └─1179656 /usr/bin/litestream replicate", - "", - "Warning: some journal files were not opened due to insufficient permissions."].join("\n") - Litestream.systemctl_command = "systemctl --user status myapp-litestream.service" - - Litestream.stub :`, stubbed_status do - info = Litestream.replicate_process - - assert_equal info[:status], "running" - assert_equal info[:pid], "1179656" - assert_equal info[:started].class, DateTime - end - end - - def test_replicate_process_ps - stubbed_ps_list = [ - "40358 ttys008 0:01.11 ruby --yjit bin/rails litestream:replicate", - "40364 ttys008 0:00.07 /path/to/litestream-ruby/exe/architecture/litestream replicate --config /path/to/app/config/litestream.yml" - ].join("\n") - - stubbed_ps_status = [ - "STAT STARTED", - "S+ Mon Jul 1 11:10:58 2024" - ].join("\n") - - stubbed_backticks = proc do |arg| - case arg - when "ps -ax | grep litestream | grep replicate" - stubbed_ps_list - when %(ps -o "state,lstart" 40364) - stubbed_ps_status - else - "" + def test_databases + stubbed_list = { + "databases" => [ + {"path" => "/var/lib/db1", "status" => "active", "last_sync_at" => "2026-02-25T10:00:00Z"}, + {"path" => "/var/lib/db2", "status" => "active", "last_sync_at" => "2026-02-25T09:00:00Z"} + ] + } + stubbed_ltx = [ + {"min_txid" => "0000000000000001", "max_txid" => "0000000000000010", "size" => 4096, + "created" => "2026-02-25T10:00:00Z", "level" => "0"}, + {"min_txid" => "0000000000000011", "max_txid" => "0000000000000020", "size" => 8192, + "created" => "2026-02-25T09:00:00Z", "level" => "1"} + ] + + Litestream::IPC.stub :list, stubbed_list do + Litestream::Commands.stub :ltx, stubbed_ltx do + databases = Litestream.databases + + assert_equal databases.size, 2 + assert_equal databases[0]["path"], "/var/lib/db1" + assert_equal databases[0]["status"], "active" + assert_equal databases[0]["ltx"], stubbed_ltx end end + end - Litestream.stub :`, stubbed_backticks do - info = Litestream.replicate_process + def test_socket_default + Litestream.socket = nil + assert_equal Litestream.socket, "/var/run/litestream.sock" + end - assert_equal info[:status], "sleeping" - assert_equal info[:pid], "40364" - assert_equal info[:started].class, DateTime - end + def test_socket_custom + Litestream.socket = "/tmp/my-litestream.sock" + assert_equal Litestream.socket, "/tmp/my-litestream.sock" end end