torikago 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,94 @@
1
+ require_relative "../test_helper"
2
+ require "fileutils"
3
+ require "tmpdir"
4
+ require "yaml"
5
+
6
+ class TorikagoPackageApiUpdaterTest < Minitest::Test
7
+ def test_update_package_api_creates_manifest_from_package_api_files
8
+ Dir.mktmpdir("torikago-package-api-updater") do |module_root|
9
+ package_api_dir = File.join(module_root, "app/package_api/foo")
10
+ FileUtils.mkdir_p(package_api_dir)
11
+
12
+ File.write(File.join(package_api_dir, "user_create_command.rb"), "")
13
+ File.write(File.join(package_api_dir, "user_find_query.rb"), "")
14
+
15
+ configuration = Torikago::Configuration.new
16
+ configuration.register(:foo, root: module_root)
17
+
18
+ updates = Torikago::PackageApiUpdater.new(configuration: configuration).call
19
+ manifest = YAML.safe_load(File.read(File.join(module_root, "package_api.yml")))
20
+
21
+ assert_equal [Pathname(File.join(module_root, "package_api.yml"))], updates.values
22
+ assert_equal(
23
+ {
24
+ "exports" => {
25
+ "Foo::UserCreateCommand" => { "allowed_callers" => [] },
26
+ "Foo::UserFindQuery" => { "allowed_callers" => [] }
27
+ }
28
+ },
29
+ manifest
30
+ )
31
+ end
32
+ end
33
+
34
+ def test_update_package_api_preserves_existing_allowed_callers
35
+ Dir.mktmpdir("torikago-package-api-updater") do |module_root|
36
+ package_api_dir = File.join(module_root, "app/package_api/foo")
37
+ FileUtils.mkdir_p(package_api_dir)
38
+
39
+ File.write(File.join(package_api_dir, "user_create_command.rb"), "")
40
+ File.write(
41
+ File.join(module_root, "package_api.yml"),
42
+ <<~YAML
43
+ exports:
44
+ Foo::UserCreateCommand:
45
+ allowed_callers:
46
+ - bar
47
+ YAML
48
+ )
49
+
50
+ configuration = Torikago::Configuration.new
51
+ configuration.register(:foo, root: module_root)
52
+
53
+ Torikago::PackageApiUpdater.new(configuration: configuration).call(:foo)
54
+ manifest = YAML.safe_load(File.read(File.join(module_root, "package_api.yml")))
55
+
56
+ assert_equal ["bar"], manifest.dig("exports", "Foo::UserCreateCommand", "allowed_callers")
57
+ end
58
+ end
59
+
60
+ def test_update_package_api_uses_a_configured_entrypoint_directory
61
+ Dir.mktmpdir("torikago-package-api-updater") do |module_root|
62
+ package_api_dir = File.join(module_root, "components/public_api/foo")
63
+ FileUtils.mkdir_p(package_api_dir)
64
+
65
+ File.write(File.join(package_api_dir, "user_create_command.rb"), "")
66
+
67
+ configuration = Torikago::Configuration.new
68
+ configuration.register(:foo, root: module_root, entrypoint: "components/public_api")
69
+
70
+ Torikago::PackageApiUpdater.new(configuration: configuration).call(:foo)
71
+ manifest = YAML.safe_load(File.read(File.join(module_root, "package_api.yml")))
72
+
73
+ assert_equal(
74
+ { "allowed_callers" => [] },
75
+ manifest.dig("exports", "Foo::UserCreateCommand")
76
+ )
77
+ end
78
+ end
79
+
80
+ def test_update_package_api_does_not_scan_parent_when_configured_entrypoint_directory_is_missing
81
+ Dir.mktmpdir("torikago-package-api-updater") do |module_root|
82
+ FileUtils.mkdir_p(File.join(module_root, "app/models/foo"))
83
+ File.write(File.join(module_root, "app/models/foo/widget.rb"), "")
84
+
85
+ configuration = Torikago::Configuration.new
86
+ configuration.register(:foo, root: module_root, entrypoint: "app/package_api")
87
+
88
+ Torikago::PackageApiUpdater.new(configuration: configuration).call(:foo)
89
+ manifest = YAML.safe_load(File.read(File.join(module_root, "package_api.yml")))
90
+
91
+ assert_equal({ "exports" => {} }, manifest)
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,83 @@
1
+ require_relative "../test_helper"
2
+
3
+ class TorikagoRegistryTest < Minitest::Test
4
+ def setup
5
+ @configuration = Torikago::Configuration.new
6
+ @configuration.register(
7
+ :foo,
8
+ root: "/modules/foo",
9
+ entrypoint: "lib/foo/box_runtime.rb",
10
+ setup: "config/box_setup.rb",
11
+ gemfile: "Gemfile"
12
+ )
13
+ end
14
+
15
+ def test_resolve_returns_a_container_for_a_registered_module
16
+ registry = Torikago::Registry.new(configuration: @configuration) do |definition|
17
+ {
18
+ name: definition.name,
19
+ root: definition.root.to_s,
20
+ entrypoint: definition.entrypoint,
21
+ setup: definition.setup,
22
+ gemfile: definition.gemfile
23
+ }
24
+ end
25
+
26
+ container = registry.resolve(:foo)
27
+
28
+ assert_equal :foo, container[:name]
29
+ assert_equal "/modules/foo", container[:root]
30
+ assert_equal "lib/foo/box_runtime.rb", container[:entrypoint]
31
+ assert_equal "config/box_setup.rb", container[:setup]
32
+ assert_equal "Gemfile", container[:gemfile]
33
+ end
34
+
35
+ def test_resolve_reuses_the_same_container_for_the_same_module
36
+ build_count = 0
37
+
38
+ registry = Torikago::Registry.new(configuration: @configuration) do |_definition|
39
+ build_count += 1
40
+ Object.new
41
+ end
42
+
43
+ first = registry.resolve(:foo)
44
+ second = registry.resolve("foo")
45
+
46
+ assert_same first, second
47
+ assert_equal 1, build_count
48
+ end
49
+
50
+ def test_resolve_fails_clearly_for_an_unknown_module
51
+ registry = Torikago::Registry.new(configuration: @configuration) do |_definition|
52
+ Object.new
53
+ end
54
+
55
+ error = assert_raises(KeyError) do
56
+ registry.resolve(:missing)
57
+ end
58
+
59
+ assert_match(/missing/, error.message)
60
+ end
61
+
62
+ def test_resolve_uses_the_container_factory_not_the_gateway
63
+ captured_definition = nil
64
+
65
+ registry = Torikago::Registry.new(configuration: @configuration) do |definition|
66
+ captured_definition = definition
67
+ Object.new
68
+ end
69
+
70
+ registry.resolve(:foo)
71
+
72
+ refute_nil captured_definition
73
+ assert_equal :foo, captured_definition.name
74
+ end
75
+
76
+ def test_resolve_builds_an_engine_container_by_default
77
+ registry = Torikago::Registry.new(configuration: @configuration)
78
+
79
+ container = registry.resolve(:foo)
80
+
81
+ assert_instance_of Torikago::EngineContainer, container
82
+ end
83
+ end
@@ -0,0 +1,11 @@
1
+ require_relative "../test_helper"
2
+
3
+ class TorikagoVersionTest < Minitest::Test
4
+ def test_has_a_version_number
5
+ refute_nil ::Torikago::VERSION
6
+ end
7
+
8
+ def test_version_uses_semver_like_format
9
+ assert_match(/\A\d+\.\d+\.\d+\z/, ::Torikago::VERSION)
10
+ end
11
+ end
data/test/torikago.rb ADDED
@@ -0,0 +1,110 @@
1
+ require_relative "test_helper"
2
+ require "open3"
3
+ require "rbconfig"
4
+
5
+ class TorikagoTest < Minitest::Test
6
+ def test_version_is_available_when_module_is_included
7
+ object = Class.new { include Torikago }.new
8
+
9
+ assert_equal Torikago::VERSION, object.version
10
+ end
11
+
12
+ def test_configure_yields_the_shared_configuration
13
+ original_configuration = Torikago.configuration
14
+
15
+ begin
16
+ yielded_configuration = nil
17
+
18
+ Torikago.configure do |config|
19
+ yielded_configuration = config
20
+ end
21
+
22
+ assert_same Torikago.configuration, yielded_configuration
23
+ ensure
24
+ Torikago.instance_variable_set(:@configuration, original_configuration)
25
+ Torikago.instance_variable_set(:@registry, nil)
26
+ Torikago.instance_variable_set(:@gateway, nil)
27
+ end
28
+ end
29
+
30
+ def test_warns_when_loaded_in_rails_without_ruby_box
31
+ script = <<~RUBY
32
+ $LOAD_PATH.unshift(ARGV.fetch(0))
33
+
34
+ module Rails
35
+ class << self
36
+ attr_accessor :application
37
+ end
38
+
39
+ self.application = Object.new
40
+ end
41
+
42
+ require "torikago"
43
+ RUBY
44
+
45
+ _stdout, stderr, status = Open3.capture3(
46
+ { "RUBY_BOX" => nil },
47
+ RbConfig.ruby,
48
+ "-e",
49
+ script,
50
+ File.expand_path("../lib", __dir__)
51
+ )
52
+
53
+ assert_predicate status, :success?, stderr
54
+ assert_match(/\[warn\].*RUBY_BOX=1/, stderr)
55
+ end
56
+
57
+ def test_does_not_warn_when_ruby_box_is_enabled
58
+ with_ruby_box_env("1") do
59
+ with_temporary_rails_constant(application: Object.new) do
60
+ assert_output(nil, "") do
61
+ Torikago.send(:warn_if_ruby_box_is_disabled_in_rails!)
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ def test_does_not_warn_outside_rails
68
+ with_ruby_box_env(nil) do
69
+ assert_output(nil, "") do
70
+ Torikago.send(:warn_if_ruby_box_is_disabled_in_rails!)
71
+ end
72
+ end
73
+ end
74
+
75
+ def test_does_not_warn_when_rails_constant_exists_but_no_application_is_booted
76
+ with_ruby_box_env(nil) do
77
+ with_temporary_rails_constant(application: nil) do
78
+ assert_output(nil, "") do
79
+ Torikago.send(:warn_if_ruby_box_is_disabled_in_rails!)
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ def with_ruby_box_env(value)
88
+ original = ENV["RUBY_BOX"]
89
+ ENV["RUBY_BOX"] = value
90
+ yield
91
+ ensure
92
+ ENV["RUBY_BOX"] = original
93
+ end
94
+
95
+ def with_temporary_rails_constant(application:)
96
+ had_rails = Object.const_defined?(:Rails)
97
+ unless had_rails
98
+ rails_module = Module.new do
99
+ singleton_class.attr_accessor :application
100
+ end
101
+ rails_module.application = application
102
+ Object.const_set(:Rails, rails_module)
103
+ end
104
+
105
+ Rails.application = application if Rails.respond_to?(:application=)
106
+ yield
107
+ ensure
108
+ Object.send(:remove_const, :Rails) if !had_rails && Object.const_defined?(:Rails)
109
+ end
110
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: torikago
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - se4weed
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: |
13
+ torikago is a Ruby gem for modular monolith runtime isolation. It boots
14
+ module-scoped runtimes with Ruby::Box and routes host app and inter-module
15
+ communication through explicit gateway and registry objects.
16
+ email:
17
+ - se4weed@gmail.com
18
+ executables:
19
+ - torikago
20
+ extensions: []
21
+ extra_rdoc_files:
22
+ - README.ja.md
23
+ files:
24
+ - LICENSE.txt
25
+ - README.ja.md
26
+ - README.md
27
+ - exe/torikago
28
+ - lib/torikago.rb
29
+ - lib/torikago/checker.rb
30
+ - lib/torikago/cli.rb
31
+ - lib/torikago/configuration.rb
32
+ - lib/torikago/current_execution.rb
33
+ - lib/torikago/engine_container.rb
34
+ - lib/torikago/errors.rb
35
+ - lib/torikago/gateway.rb
36
+ - lib/torikago/package_api_updater.rb
37
+ - lib/torikago/registry.rb
38
+ - lib/torikago/version.rb
39
+ - test/test_helper.rb
40
+ - test/torikago.rb
41
+ - test/torikago/checker.rb
42
+ - test/torikago/cli.rb
43
+ - test/torikago/configuration.rb
44
+ - test/torikago/engine_container.rb
45
+ - test/torikago/gateway.rb
46
+ - test/torikago/package_api_updater.rb
47
+ - test/torikago/registry.rb
48
+ - test/torikago/version.rb
49
+ homepage: "https://github.com/se4weed/torikago"
50
+ licenses:
51
+ - MIT
52
+ metadata:
53
+ rubygems_mfa_required: "true"
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ -
60
+ - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 4.0.3
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ -
66
+ - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ requirements: []
70
+ rubygems_version: 4.1.0.dev
71
+ specification_version: 4
72
+ summary: "Runtime isolation for modular monoliths built around Ruby::Box"
73
+ test_files: []