delfos 0.0.1.pre.rc1 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/delfos.rb +22 -78
  3. data/lib/delfos/call_stack.rb +39 -0
  4. data/lib/delfos/call_stack/stack.rb +59 -0
  5. data/lib/delfos/file_system/common_path.rb +62 -0
  6. data/lib/delfos/{distance/calculation.rb → file_system/distance_calculation.rb} +4 -15
  7. data/lib/delfos/file_system/path_determination.rb +37 -0
  8. data/lib/delfos/{distance → file_system}/relation.rb +1 -1
  9. data/lib/delfos/method_logging.rb +32 -49
  10. data/lib/delfos/method_logging/call_site_parsing.rb +74 -0
  11. data/lib/delfos/method_logging/code_location.rb +34 -98
  12. data/lib/delfos/method_logging/{args.rb → method_parameters.rb} +17 -18
  13. data/lib/delfos/neo4j.rb +58 -0
  14. data/lib/delfos/neo4j/batch/execution.rb +149 -0
  15. data/lib/delfos/neo4j/{execution_persistence.rb → call_stack_query.rb} +12 -22
  16. data/lib/delfos/neo4j/distance/call_site_fetcher.rb +19 -0
  17. data/lib/delfos/neo4j/distance/update.rb +50 -0
  18. data/lib/delfos/neo4j/informer.rb +62 -34
  19. data/lib/delfos/neo4j/query_execution/errors.rb +30 -0
  20. data/lib/delfos/neo4j/query_execution/http.rb +61 -0
  21. data/lib/delfos/neo4j/query_execution/http_query.rb +67 -0
  22. data/lib/delfos/neo4j/query_execution/sync.rb +35 -0
  23. data/lib/delfos/neo4j/query_execution/transactional.rb +68 -0
  24. data/lib/delfos/neo4j/schema.rb +73 -0
  25. data/lib/delfos/patching/basic_object.rb +1 -5
  26. data/lib/delfos/patching/method_cache.rb +83 -0
  27. data/lib/delfos/patching/method_override.rb +76 -66
  28. data/lib/delfos/patching/module_defining_methods.rb +105 -0
  29. data/lib/delfos/patching/unstubber.rb +34 -0
  30. data/lib/delfos/setup.rb +88 -0
  31. metadata +42 -15
  32. data/lib/delfos/common_path.rb +0 -58
  33. data/lib/delfos/execution_chain.rb +0 -75
  34. data/lib/delfos/method_logging/added_methods.rb +0 -67
  35. data/lib/delfos/neo4j/distance_update.rb +0 -73
  36. data/lib/delfos/neo4j/query_execution.rb +0 -79
  37. data/lib/delfos/patching/unstubbing_spec_helper.rb +0 -58
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+ module Delfos
3
+ module Patching
4
+ # containers for the individual modules created to log each method call
5
+ module ClassMethodLogging
6
+ end
7
+
8
+ module InstanceMethodLogging
9
+ end
10
+
11
+ module ModuleDefiningMethods
12
+ def module_definition(klass, method_name, class_method, &block)
13
+ definer = ModuleDefiner.new(klass, method_name, class_method)
14
+
15
+ if block_given?
16
+ definer.perform(&block)
17
+ else
18
+ definer.perform
19
+ end
20
+ end
21
+ end
22
+
23
+ class ModuleDefiner
24
+ attr_reader :klass, :method_name, :class_method
25
+
26
+ def initialize(klass, method_name, class_method)
27
+ @klass, @method_name, @class_method = klass, method_name, class_method
28
+ end
29
+
30
+ def perform(&block)
31
+ safe_method_name = safe_method_name()
32
+ safe_class_name = safe_class_name()
33
+ module_type = class_method ? "ClassMethodLogging" : "InstanceMethodLogging"
34
+ find_or_create = method(:find_or_create)
35
+
36
+ m = nil
37
+ Patching.const_get(module_type).instance_eval do
38
+ namespace = find_or_create.call(self, safe_class_name)
39
+
40
+ m = find_or_create.call(namespace, safe_method_name)
41
+
42
+ m.class_eval(&block) if block_given?
43
+
44
+ m
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def safe_class_name
51
+ module_safe_name(klass.name || klass.to_s)
52
+ end
53
+
54
+ def safe_method_name
55
+ module_safe_name(method_name.to_s)
56
+ end
57
+
58
+ def find_or_create(container, module_name)
59
+ module_name = module_name.tr(":", "_")
60
+
61
+ result = container.const_get(module_name)
62
+
63
+ # E.g. finding `::A' instead of Delfos::Patching::InstanceMethodLogging::A
64
+ if result == klass || result.name[module_name] == result.name
65
+ create(container, module_name)
66
+ else
67
+ result
68
+ end
69
+ rescue NameError => e
70
+ raise unless e.message[module_name]
71
+ create(container, module_name)
72
+ end
73
+
74
+ def create(container, module_name)
75
+ m = Module.new
76
+
77
+ container.const_set(module_name, m)
78
+ return m
79
+ rescue Exception => e
80
+ m
81
+ end
82
+
83
+ def module_safe_name(string, _uppercase_first_letter = true)
84
+ string = string.sub(/^[a-z\d]*/) { $&.capitalize }
85
+
86
+ string.
87
+ gsub(/(?:_|(\/))([a-z\d]*)/) { "#{Regexp.last_match(1)}#{Regexp.last_match(2).capitalize}" }.
88
+ gsub("/", "::").
89
+ gsub(/\=/, "Equals").
90
+ gsub(/\<\=\>/, "Spaceship").
91
+ gsub(/\<\=/, "LessThanOrEqualTo").
92
+ gsub(/\>\=/, "GreaterThanOrEqualTo").
93
+ gsub(/\#\<Class\:0x(.*)\>/) { "AnonymousClass_#{Regexp.last_match(1)}" }.
94
+ gsub(/\>/, "GreaterThan").
95
+ gsub(/\</, "LessThan").
96
+ gsub(/!\~/, "NotMatchOperator").
97
+ gsub(/\~/, "MatchOperator").
98
+ gsub(/\?/, "QuestionMark").
99
+ gsub(/\!$/, "Bang").
100
+ gsub(/\+/, "Plus").
101
+ gsub(/\[\]/, "SquareBrackets")
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+ module Delfos
3
+ module Patching
4
+ class Unstubber
5
+ extend ModuleDefiningMethods
6
+
7
+ def self.unstub_all!
8
+ MUTEX.synchronize do
9
+ Thread.current[:__delfos_disable_patching] = true
10
+ end
11
+
12
+ MethodCache.each_method do |klass_name, method, class_method|
13
+ klass = eval(klass_name)
14
+
15
+ unstub!(klass, method.name, class_method)
16
+ end
17
+
18
+ MUTEX.synchronize do
19
+ Thread.current[:__delfos_disable_patching] = false
20
+ end
21
+ end
22
+
23
+ def self.unstub!(klass, method_name, class_method)
24
+ module_definition(klass, method_name, class_method) do |m|
25
+ begin
26
+ remove_method :"#{method_name}"
27
+ rescue NameError => e
28
+ raise unless e.message["method `#{method_name}' not defined in"]
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+ module Delfos
3
+ module Setup
4
+ extend self
5
+ attr_accessor :neo4j
6
+
7
+ def perform!(call_site_logger: nil, application_directories: nil)
8
+ self.application_directories = application_directories
9
+ self.call_site_logger = call_site_logger
10
+
11
+ perform_patching!
12
+ end
13
+
14
+ def application_directories=(dirs)
15
+ dirs ||= %w(app lib)
16
+ require "pathname"
17
+ Delfos.application_directories = Array(dirs).map { |f| Pathname.new(File.expand_path(f.to_s)) }
18
+ end
19
+
20
+ def call_site_logger
21
+ @call_site_logger ||= default_call_site_logger
22
+ end
23
+
24
+ def call_site_logger=(call_site_logger)
25
+ @call_site_logger = call_site_logger || default_call_site_logger
26
+ end
27
+
28
+ def default_call_site_logger
29
+ Delfos.setup_neo4j!
30
+
31
+ require "delfos/neo4j/informer"
32
+ Delfos:: Neo4j::Informer.new
33
+ end
34
+
35
+ def reset!
36
+ if defined? Delfos::CallStack
37
+ Delfos::CallStack.pop_until_top!
38
+ Delfos::CallStack.reset!
39
+ end
40
+
41
+ if defined? Delfos::Neo4j::Batch::Execution
42
+ begin
43
+ Delfos::Neo4j::Batch::Execution.flush!
44
+ rescue
45
+ Delfos::Neo4j::QueryExecution::ExpiredTransaction
46
+ end
47
+
48
+ Delfos::Neo4j::Batch::Execution.reset!
49
+ end
50
+
51
+ # unstubbing depends upon MethodCache being still defined
52
+ # so this order is important
53
+ unstub_all!
54
+ remove_cached_methods!
55
+
56
+ remove_patching!
57
+
58
+ Delfos::MethodLogging.reset! if defined?(Delfos::MethodLogging) && Delfos::MethodLogging.respond_to?(:reset!)
59
+
60
+ Delfos.neo4j = nil
61
+ Delfos.logger = nil
62
+ Delfos.application_directories = nil
63
+ Delfos.call_site_logger = nil
64
+ @call_site_logger = nil
65
+ Delfos.neo4j = nil
66
+ end
67
+
68
+ def unstub_all!
69
+ return unless defined? Delfos::Patching::Unstubber
70
+
71
+ Delfos::Patching::Unstubber.unstub_all!
72
+ end
73
+
74
+ def remove_cached_methods!
75
+ return unless defined? Delfos::Patching::MethodCache
76
+
77
+ Delfos::Patching::MethodCache.reset!
78
+ end
79
+
80
+ def remove_patching!
81
+ load "delfos/patching/basic_object_remove.rb"
82
+ end
83
+
84
+ def perform_patching!
85
+ load "delfos/patching/basic_object.rb"
86
+ end
87
+ end
88
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: delfos
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.pre.rc1
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Burns
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-12-08 00:00:00.000000000 Z
11
+ date: 2016-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: binding_of_caller
@@ -30,6 +30,20 @@ dependencies:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: 0.7.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: webmock
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
33
47
  - !ruby/object:Gem::Dependency
34
48
  name: pry-byebug
35
49
  requirement: !ruby/object:Gem::Requirement
@@ -99,22 +113,35 @@ extensions: []
99
113
  extra_rdoc_files: []
100
114
  files:
101
115
  - lib/delfos.rb
102
- - lib/delfos/common_path.rb
103
- - lib/delfos/distance/calculation.rb
104
- - lib/delfos/distance/relation.rb
105
- - lib/delfos/execution_chain.rb
116
+ - lib/delfos/call_stack.rb
117
+ - lib/delfos/call_stack/stack.rb
118
+ - lib/delfos/file_system/common_path.rb
119
+ - lib/delfos/file_system/distance_calculation.rb
120
+ - lib/delfos/file_system/path_determination.rb
121
+ - lib/delfos/file_system/relation.rb
106
122
  - lib/delfos/method_logging.rb
107
- - lib/delfos/method_logging/added_methods.rb
108
- - lib/delfos/method_logging/args.rb
123
+ - lib/delfos/method_logging/call_site_parsing.rb
109
124
  - lib/delfos/method_logging/code_location.rb
110
- - lib/delfos/neo4j/distance_update.rb
111
- - lib/delfos/neo4j/execution_persistence.rb
125
+ - lib/delfos/method_logging/method_parameters.rb
126
+ - lib/delfos/neo4j.rb
127
+ - lib/delfos/neo4j/batch/execution.rb
128
+ - lib/delfos/neo4j/call_stack_query.rb
129
+ - lib/delfos/neo4j/distance/call_site_fetcher.rb
130
+ - lib/delfos/neo4j/distance/update.rb
112
131
  - lib/delfos/neo4j/informer.rb
113
- - lib/delfos/neo4j/query_execution.rb
132
+ - lib/delfos/neo4j/query_execution/errors.rb
133
+ - lib/delfos/neo4j/query_execution/http.rb
134
+ - lib/delfos/neo4j/query_execution/http_query.rb
135
+ - lib/delfos/neo4j/query_execution/sync.rb
136
+ - lib/delfos/neo4j/query_execution/transactional.rb
137
+ - lib/delfos/neo4j/schema.rb
114
138
  - lib/delfos/patching/basic_object.rb
115
139
  - lib/delfos/patching/basic_object_remove.rb
140
+ - lib/delfos/patching/method_cache.rb
116
141
  - lib/delfos/patching/method_override.rb
117
- - lib/delfos/patching/unstubbing_spec_helper.rb
142
+ - lib/delfos/patching/module_defining_methods.rb
143
+ - lib/delfos/patching/unstubber.rb
144
+ - lib/delfos/setup.rb
118
145
  homepage: https://github.com/markburns/delfos
119
146
  licenses:
120
147
  - MIT
@@ -131,12 +158,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
131
158
  version: '0'
132
159
  required_rubygems_version: !ruby/object:Gem::Requirement
133
160
  requirements:
134
- - - ">"
161
+ - - ">="
135
162
  - !ruby/object:Gem::Version
136
- version: 1.3.1
163
+ version: '0'
137
164
  requirements: []
138
165
  rubyforge_project:
139
- rubygems_version: 2.5.1
166
+ rubygems_version: 2.5.2
140
167
  signing_key:
141
168
  specification_version: 4
142
169
  summary: Runtime type analysis
@@ -1,58 +0,0 @@
1
- # frozen_string_literal: true
2
- require "pathname"
3
-
4
- module Delfos
5
- module CommonPath
6
- class << self
7
- SEPARATOR = "/"
8
-
9
- def included_in?(p1, paths)
10
- paths = paths.map do |p2|
11
- common = common_parent_directory_path(p1, p2)
12
- common.to_s.length >= p2.to_s.length
13
- end
14
-
15
- paths.compact.detect { |v| v }
16
- end
17
-
18
- def common_parent_directory_path(path_a, path_b)
19
- dirs = [File.expand_path(path_a.to_s), File.expand_path(path_b.to_s)]
20
-
21
- dir1, dir2 = dirs.minmax.map { |dir| dir.split(SEPARATOR) }
22
-
23
- path_from(dir1, dir2, path_a, path_b)
24
- end
25
-
26
- private
27
-
28
- def path_from(dir1, dir2, path_a, path_b)
29
- common_path = common_path(dir1, dir2)
30
- common_path, path_a, path_b = append_trailing_slashes!(common_path, path_a, path_b)
31
-
32
- Pathname.new(common_path) if valid_length?(common_path, path_a, path_b)
33
- end
34
-
35
- def valid_length?(common_path, path_a, path_b)
36
- (common_path.to_s.length <= path_a.to_s.length) || (common_path.to_s.length <= path_b.to_s.length)
37
- end
38
-
39
- def common_path(dir1, dir2)
40
- dir1.
41
- zip(dir2).
42
- take_while { |dn1, dn2| dn1 == dn2 }.
43
- map(&:first).
44
- join(SEPARATOR)
45
- end
46
-
47
- def append_trailing_slashes!(*paths)
48
- paths.map do |path|
49
- if Pathname.new(path).directory?
50
- path += SEPARATOR if path && path.to_s[-1] != SEPARATOR
51
- end
52
-
53
- path
54
- end
55
- end
56
- end
57
- end
58
- end
@@ -1,75 +0,0 @@
1
- # frozen_string_literal: true
2
- require_relative "neo4j/execution_persistence"
3
-
4
- module Delfos
5
- class ExecutionChain
6
- EXECUTION_CHAIN_MUTEX = Mutex.new
7
-
8
- def self.reset!
9
- EXECUTION_CHAIN_MUTEX.synchronize do
10
- Thread.current[:_delfos__execution_chain] = nil
11
- end
12
- end
13
-
14
- def self.execution_chain
15
- EXECUTION_CHAIN_MUTEX.synchronize do
16
- Thread.current[:_delfos__execution_chain] ||= new
17
- end
18
- end
19
-
20
- def self.push(method_object)
21
- execution_chain.push(method_object)
22
- end
23
-
24
- def self.pop
25
- execution_chain.pop
26
- end
27
-
28
- def push(method_object)
29
- call_sites.push(method_object)
30
- self.stack_depth += 1
31
-
32
- self.execution_count += self.stack_depth == 1 ? 1 : 0
33
- end
34
-
35
- def pop
36
- popping_empty_stack! if self.stack_depth.zero?
37
-
38
- self.stack_depth -= 1
39
-
40
- save_and_reset! if self.stack_depth.zero?
41
- end
42
-
43
- def stack_depth
44
- @stack_depth ||= 0
45
- end
46
-
47
- def execution_count
48
- @execution_count ||= 0
49
- end
50
-
51
- def call_sites
52
- @call_sites ||= []
53
- end
54
-
55
- def step_count
56
- call_sites.length
57
- end
58
-
59
- attr_writer :stack_depth, :step_count, :execution_count, :call_sites
60
-
61
- private
62
-
63
- class PoppingEmptyStackError < StandardError
64
- end
65
-
66
- def popping_empty_stack!
67
- raise PoppingEmptyStackError
68
- end
69
-
70
- def save_and_reset!
71
- Neo4j::ExecutionPersistence.save!(self) if call_sites.length.positive?
72
- self.call_sites = []
73
- end
74
- end
75
- end