# Copyright 2016 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require "helper"

describe Google::Cloud::Trace::Project, :mock_trace do
  MockPagedEnum = ::Struct.new :page

  let(:simple_trace_id) { "0123456789abcdef0123456789abcdef" }
  let(:simple_span_id) { 54321 }
  let(:simple_span_name) { "/path/to/resource" }
  let(:simple_span_start) { Time.at 10001, 123 }
  let(:simple_span_end) { Time.at 10002, 456 }
  let(:simple_span_start_proto) { Google::Protobuf::Timestamp.new seconds: 10001, nanos: 123000 }
  let(:simple_span_end_proto) { Google::Protobuf::Timestamp.new seconds: 10002, nanos: 456000 }
  let(:simple_span_labels) { { "foo" => "bar" } }
  let(:simple_span_proto) {
    Google::Cloud::Trace::V1::TraceSpan.new \
      span_id: simple_span_id,
      kind: :RPC_SERVER,
      name: simple_span_name,
      start_time: simple_span_start_proto,
      end_time: simple_span_end_proto,
      parent_span_id: 0,
      labels: simple_span_labels
  }
  let(:simple_trace_proto) {
    Google::Cloud::Trace::V1::Trace.new \
      project_id: project,
      trace_id: simple_trace_id,
      spans: [simple_span_proto]
  }
  let(:simple_traces_proto) {
    traces_proto = Google::Cloud::Trace::V1::Traces.new
    traces_proto.traces.push simple_trace_proto
    traces_proto
  }
  let(:simple_trace_context) { Stackdriver::Core::TraceContext.new trace_id: simple_trace_id }
  let(:simple_trace) {
    trace = Google::Cloud::Trace::TraceRecord.new project, simple_trace_context
    trace.create_span simple_span_name,
                      span_id: simple_span_id,
                      kind: Google::Cloud::Trace::SpanKind::RPC_SERVER,
                      start_time: simple_span_start,
                      end_time: simple_span_end,
                      labels: simple_span_labels
    trace
  }

  let(:second_trace_id) { "fedcba9876543210fedcba9876543210" }
  let(:second_span_id) { 98765 }
  let(:second_span_name) { "/path/to/resource" }
  let(:second_span_start) { Time.at 10003, 123 }
  let(:second_span_end) { Time.at 10004, 456 }
  let(:second_span_start_proto) { Google::Protobuf::Timestamp.new seconds: 10003, nanos: 123000 }
  let(:second_span_end_proto) { Google::Protobuf::Timestamp.new seconds: 10004, nanos: 456000 }
  let(:second_span_labels) { { "foo" => "baz" } }
  let(:second_span_proto) {
    Google::Cloud::Trace::V1::TraceSpan.new \
      span_id: second_span_id,
      kind: :RPC_SERVER,
      name: second_span_name,
      start_time: second_span_start_proto,
      end_time: second_span_end_proto,
      parent_span_id: 0,
      labels: second_span_labels
  }
  let(:second_trace_proto) {
    Google::Cloud::Trace::V1::Trace.new \
      project_id: project,
      trace_id: second_trace_id,
      spans: [second_span_proto]
  }
  let(:second_trace_context) { Stackdriver::Core::TraceContext.new trace_id: second_trace_id }
  let(:second_trace) {
    trace = Google::Cloud::Trace::TraceRecord.new project, second_trace_context
    trace.create_span second_span_name,
                      span_id: second_span_id,
                      kind: Google::Cloud::Trace::SpanKind::RPC_SERVER,
                      start_time: second_span_start,
                      end_time: second_span_end,
                      labels: second_span_labels
    trace
  }

  let(:range_start_proto) { Google::Protobuf::Timestamp.new seconds: 10000, nanos: 0 }
  let(:range_end_proto) { Google::Protobuf::Timestamp.new seconds: 10010, nanos: 0 }
  let(:range_start) { Time.at 10000, 0 }
  let(:range_end) { Time.at 10010, 0 }

  let(:next_page_token) { "next" }
  let(:gapic_page) {
    response = OpenStruct.new(resource: [simple_trace_proto, second_trace_proto],
                              next_page_token: next_page_token)
    Gapic::PagedEnumerable::Page.new response, :resource, nil
  }
  let(:gapic_paged_enum) {
    MockPagedEnum.new gapic_page
  }

  it "knows the project identifier" do
    _(tracer).must_be_kind_of Google::Cloud::Trace::Project
    _(tracer.project).must_equal project
  end

  it "gets a single trace" do
    mock = Minitest::Mock.new
    mock.expect :get_trace, simple_trace_proto, project_id: project, trace_id: simple_trace_id
    tracer.service.mocked_lowlevel_client = mock

    actual_trace = tracer.get_trace simple_trace_id

    mock.verify
    _(actual_trace).must_equal simple_trace
  end

  it "lists traces" do
    mock = Minitest::Mock.new
    mock.expect :list_traces, gapic_paged_enum,
                project_id: project,
                start_time: range_start_proto,
                end_time: range_end_proto,
                view: nil,
                page_size: nil,
                filter: nil,
                order_by: nil,
                page_token: nil
    tracer.service.mocked_lowlevel_client = mock

    actual_result = tracer.list_traces range_start, range_end

    mock.verify
    _(actual_result).must_be_kind_of Google::Cloud::Trace::ResultSet
    _(actual_result.project).must_equal project
    _(actual_result.next_page_token).must_equal next_page_token
    _(actual_result.start_time).must_equal range_start
    _(actual_result.end_time).must_equal range_end
    _(actual_result.results_pending?).must_equal true
    _(actual_result.to_a).must_equal [simple_trace, second_trace]
  end

  it "patches a trace" do
    mock = Minitest::Mock.new
    mock.expect :patch_traces, nil, project_id: project, traces: simple_traces_proto
    tracer.service.mocked_lowlevel_client = mock

    tracer.patch_traces simple_trace

    mock.verify
  end
end
