Welcome to mirror list, hosted at ThFree Co, Russian Federation.

pprof_builder_spec.rb « cloud_profiler_agent « spec « cloud_profiler_agent « gems « vendor - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 5c94a8e1e445ed7d3a41a6deeaa83fbabee14d24 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# frozen_string_literal: true

require 'cloud_profiler_agent'

RSpec.describe CloudProfilerAgent::PprofBuilder, feature_category: :application_performance do
  subject { described_class.new(profile, start_time, end_time) }

  # load_profile loads one of the example profiles created by
  # script/generate_profile.rb
  def load_profile(name)
    # We are disabling this security check since we are loading static files that we generated ourselves, and it is
    # only used in specs. This is the same method StackProf uses:
    # https://github.com/tmm1/stackprof/blob/master/lib/stackprof/report.rb#L14
    Marshal.load(File.binread(File.expand_path("#{name}.stackprof", __dir__))) # rubocop:disable Security/MarshalLoad
  end

  def get_str(index)
    message.string_table.fetch(index)
  end

  let(:start_time) { Time.new(2020, 10, 31, 17, 12, 0) }
  let(:end_time) { Time.new(2020, 10, 31, 17, 12, 30) }

  # message is the protobuf object, which typically gets serialized and gzip'd
  # before being sent to the Profiler API or written to disk. Rather than
  # unzipping and deserializing all the time, we will be making a lot of
  # assertions about the message directly.
  let(:message) { subject.message }

  context 'with :cpu profile' do
    let(:profile) { load_profile(:cpu) }

    it 'has a sample type of [["cpu", "nanoseconds"]]' do
      expect(message.sample_type.length).to eq(1)

      sample_type = message.sample_type.first
      expect(get_str(sample_type.type)).to eq('cpu')
      expect(get_str(sample_type.unit)).to eq('nanoseconds')
    end

    it 'has a period of 100,000 cpu nanoseconds' do
      expect(message.period).to eq(100_000)
      period_type = message.period_type
      expect(get_str(period_type.type)).to eq('cpu')
      expect(get_str(period_type.unit)).to eq('nanoseconds')
    end

    it 'has a duration of 30 seconds' do
      expect(message.duration_nanos).to eq(30 * 1_000_000_000)
    end

    it 'has the start time' do
      expect(message.time_nanos).to eq(start_time.to_i * 1_000_000_000)
    end
  end

  context 'with :wall profile' do
    let(:profile) { load_profile(:wall) }

    it 'has a sample type of [["wall", "nanoseconds"]]' do
      expect(message.sample_type.length).to eq(1)

      sample_type = message.sample_type.first
      expect(get_str(sample_type.type)).to eq('wall')
      expect(get_str(sample_type.unit)).to eq('nanoseconds')
    end

    it 'has a period of 100,000 wall nanoseconds' do
      expect(message.period).to eq(100_000)
      period_type = message.period_type
      expect(get_str(period_type.type)).to eq('wall')
      expect(get_str(period_type.unit)).to eq('nanoseconds')
    end

    it 'has a sum time of about 1 second' do
      sum_nanos = 0
      message.sample.each do |sample|
        sum_nanos += sample.value.first
      end

      expect(sum_nanos).to be_within(1_000_000).of(1_000_000_000)
    end
  end

  context 'with :object profile' do
    let(:profile) { load_profile(:object) }

    it 'has a sample type of [["alloc_objects", "count"]]' do
      expect(message.sample_type.length).to eq(1)

      sample_type = message.sample_type.first
      expect(get_str(sample_type.type)).to eq('alloc_objects')
      expect(get_str(sample_type.unit)).to eq('count')
    end

    it 'has a period of 100 alloc_objects count' do
      expect(message.period).to eq(100)
      period_type = message.period_type
      expect(get_str(period_type.type)).to eq('alloc_objects')
      expect(get_str(period_type.unit)).to eq('count')
    end
  end
end