[SCM] ci-tooling packaging branch, master, updated. 98960681c388441d8f3c6ad779b55cf291ef7abf

Harald Sitter apachelogger-guest at moszumanska.debian.org
Thu Dec 10 11:04:49 UTC 2015


Gitweb-URL: http://git.debian.org/?p=pkg-kde/ci-tooling.git;a=commitdiff;h=308e98e

The following commit has been merged in the master branch:
commit 308e98e437d189d00a1244fe13e8664bb5cedd0d
Author: Harald Sitter <sitter at kde.org>
Date:   Thu Dec 10 12:03:59 2015 +0100

    treat lp.rb to full testing coverage to avoid breakage moving forward
---
 lib/lp.rb                                |  48 +++--
 test/data/lp/ubuntu-archive-primary.json |   1 +
 test/data/lp/ubuntu-archives1.json       |   1 +
 test/data/lp/ubuntu-archives2.json       |   1 +
 test/data/lp/ubuntu.json                 |   1 +
 test/test_lp.rb                          | 348 ++++++++++++++++++++++++++-----
 6 files changed, 326 insertions(+), 74 deletions(-)

diff --git a/lib/lp.rb b/lib/lp.rb
index 4c27b4a..071e795 100644
--- a/lib/lp.rb
+++ b/lib/lp.rb
@@ -46,6 +46,9 @@ require_relative 'retry'
 
 # A simple launchpad REST API wrapper.
 module Launchpad
+  IO_RETRIES = 2
+  @io_retry_sleeps = 8
+
   @mutex = Mutex.new
   @token = nil
   @conf_path = ENV['HOME']
@@ -121,7 +124,7 @@ module Launchpad
     if (token = Launchpad.token)
       # Token internally URIfies again without checking if it already has
       # a URI, so simply give it a string...
-      Retry.retry_it(times: 2, sleep: 8) do
+      Retry.retry_it(times: IO_RETRIES, sleep: @io_retry_sleeps) do
         response = token.get(uri.to_s)
         unless response.is_a? Net::HTTPSuccess
           fail Net::HTTPRetriableError.new(response.body, response)
@@ -142,13 +145,15 @@ module Launchpad
     # Launchpad employs server-side caching, which is nice but for our purposes
     # 90% of the time we need current data, otherwise we wouldn't be polling
     # on a schedule.
-    d = nil
-    Net::HTTP.start(uri.hostname,
-                    uri.port,
+    Net::HTTP.start(uri.hostname, uri.port,
                     use_ssl: (uri.scheme == 'https')) do |http|
-      d = http.request_get(uri, 'Cache-Control' => 'max-age=0').body
+      response = http.request_get(uri, 'Cache-Control' => 'max-age=0')
+      unless response.is_a?(Net::HTTPSuccess)
+        fail Net::HTTPRetriableError.new(response.body, response)
+      end
+      return response.body
     end
-    d
+    nil
   end
 
   # HTTP POST. Only possible after {authenticate} was used to get a token!
@@ -158,7 +163,7 @@ module Launchpad
     token = Launchpad.token
     fail 'Launchpad.authenticate must be called before any post' unless token
     # Posting always requires a token.
-    Retry.retry_it(times: 2, sleep: 8) do
+    Retry.retry_it(times: IO_RETRIES, sleep: @io_retry_sleeps) do
       response = token.post(uri.path, uri.query)
       unless response.is_a? Net::HTTPSuccess
         fail Net::HTTPRetriableError.new(response.body, response)
@@ -196,16 +201,27 @@ module Launchpad
     end
 
     # @!visibility private
+    # Build parameters.
+    # For convenience reasons passing a parameter object that itself
+    # responds to self_link will result in its self_link being passed.
     def build_params(name, params = {})
       params ||= {}
-      params['ws.op'] = name.to_s.chomp('!')
       params.each do |key, value|
-        next unless value.respond_to?(:fetch) && value.fetch('self_link', false)
-        params[key] = value['self_link']
+        unless value.respond_to?(:to_h) && value.to_h.fetch(:self_link, false)
+          next
+        end
+        params[key] = value.to_h.fetch(:self_link)
       end
+      params['ws.op'] = name.to_s.chomp('!')
       params
     end
 
+    def build_uri(params)
+      uri = URI(self['self_link'])
+      uri.query = URI.encode_www_form(params)
+      uri
+    end
+
     # @!visibility private
     def http_get(uri)
       ret = []
@@ -236,19 +252,15 @@ module Launchpad
         return method_missing_collection_link(name)
       end
 
-      # Build parameters.
-      # For convenience reasons passing a parameter object that itself
-      # responds to self_link will result in its self_link being passed.
-      params = build_params(name, args[0])
-
-      uri = URI(self['self_link'])
-      uri.query = URI.encode_www_form(params)
+      uri = build_uri(build_params(name, args[0]))
 
       # Try to call as a 'function' on the API
       #   foo! causes a POST
       #   else we GET
       return Launchpad.post(uri) if name.to_s.end_with?('!')
-      http_get(uri)
+      ret = http_get(uri)
+      super unless ret
+      ret
     end
 
     # Construct a {Rubber} from a JSON string.
diff --git a/test/data/lp/ubuntu-archive-primary.json b/test/data/lp/ubuntu-archive-primary.json
new file mode 100644
index 0000000..451de5c
--- /dev/null
+++ b/test/data/lp/ubuntu-archive-primary.json
@@ -0,0 +1 @@
+{"external_dependencies": null, "reference": "ubuntu", "build_debug_symbols": true, "private": false, "processors_collection_link": "https://api.launchpad.net/devel/ubuntu/+archive/primary/processors", "require_virtualized": false, "suppress_subscription_notifications": false, "enabled_restricted_processors_collection_link": "https://api.launchpad.net/devel/ubuntu/+archive/primary/enabled_restricted_processors", "publish_debug_symbols": false, "http_etag": "\"a5375f5b11e21d004350f3df4db8a380e71052d3-786500da679ba8ca645ee762507354ae210dba76\"", "self_link": "https://api.launchpad.net/devel/ubuntu/+archive/primary", "resource_type_link": "https://api.launchpad.net/devel/#archive", "status": "Active", "dependencies_collection_link": "https://api.launchpad.net/devel/ubuntu/+archive/primary/dependencies", "authorized_size": null, "displayname": "Primary Archive for Ubuntu", "description": "The Ubuntu Distribution aims to produce a single-CD installable operating system that includes everything needed to run a typical desktop or server machine, anywhere in the world. We emphasise three things:

 1. Free of Charge. Ubuntu is absolutely free of charge, and will remain that way.

 2. Licence Freedom. Ubuntu includes only Free Software applications. You are free to modify or change any aspect of your Ubuntu system.

 3. Ease of Use. We aim to make Ubuntu the easiest version of Linux to install and use immediately. We put a lot of effort into making sure that the default configuration is comprehensive but sane, so that you will find your new desktop familiar but not overwhelming.

Ubuntu also includes more software than any other operating system, on its network of software repositories. Once your system is installed you can simply call up a list of all the existing tools out there and choose any of them for immediate installation over the internet.
", "permit_obsolete_series_uploads": true, "relative_build_score": 0, "name": "primary", "distribution_link": "https://api.launchpad.net/devel/ubuntu", "web_link": "https://launchpad.net/ubuntu/+archive/primary", "owner_link": "https://api.launchpad.net/devel/~ubuntu-archive", "signing_key_fingerprint": null}
diff --git a/test/data/lp/ubuntu-archives1.json b/test/data/lp/ubuntu-archives1.json
new file mode 100644
index 0000000..35fb519
--- /dev/null
+++ b/test/data/lp/ubuntu-archives1.json
@@ -0,0 +1 @@
+{"total_size": 2, "start": 0, "next_collection_link": "https://api.launchpad.net/devel/ubuntu/archives?ws.size=1\u0026memo=1\u0026ws.start=1", "entries": [{"external_dependencies": null, "reference": "ubuntu", "build_debug_symbols": true, "private": false, "processors_collection_link": "https://api.launchpad.net/devel/ubuntu/+archive/primary/processors", "require_virtualized": false, "suppress_subscription_notifications": false, "enabled_restricted_processors_collection_link": "https://api.launchpad.net/devel/ubuntu/+archive/primary/enabled_restricted_processors", "publish_debug_symbols": false, "http_etag": "\"c77bfcfdf014676ee76606e0d2a212ab0ab40922-786500da679ba8ca645ee762507354ae210dba76\"", "self_link": "https://api.launchpad.net/devel/ubuntu/+archive/primary", "resource_type_link": "https://api.launchpad.net/devel/#archive", "status": "Active", "dependencies_collection_link": "https://api.launchpad.net/devel/ubuntu/+archive/primary/dependencies", "authorized_size": null, "displayname": "Primary Archive for Ubuntu", "description": "The Ubuntu Distribution aims to produce a single-CD installable operating system that includes everything needed to run a typical desktop or server machine, anywhere in the world. We emphasise three things:

 1. Free of Charge. Ubuntu is absolutely free of charge, and will remain that way.

 2. Licence Freedom. Ubuntu includes only Free Software applications. You are free to modify or change any aspect of your Ubuntu system.

 3. Ease of Use. We aim to make Ubuntu the easiest version of Linux to install and use immediately. We put a lot of effort into making sure that the default configuration is comprehensive but sane, so that you will find your new desktop familiar but not overwhelming.

Ubuntu also includes more software than any other operating system, on its network of software repositories. Once your system is installed you can simply call up a list of all the existing tools out there and choose any of them for immediate installation over the internet.
", "permit_obsolete_series_uploads": true, "relative_build_score": 0, "name": "primary", "distribution_link": "https://api.launchpad.net/devel/ubuntu", "web_link": "https://launchpad.net/ubuntu/+archive/primary", "owner_link": "https://api.launchpad.net/devel/~ubuntu-archive", "signing_key_fingerprint": null}], "resource_type_link" : "https://api.launchpad.net/devel/#archive-page-resource"}
diff --git a/test/data/lp/ubuntu-archives2.json b/test/data/lp/ubuntu-archives2.json
new file mode 100644
index 0000000..d149aff
--- /dev/null
+++ b/test/data/lp/ubuntu-archives2.json
@@ -0,0 +1 @@
+{"total_size": 2, "start": 2, "prev_collection_link": "https://api.launchpad.net/devel/ubuntu/archives", "entries": [{"external_dependencies": null, "reference": "ubuntu/partner", "build_debug_symbols": true, "private": false, "processors_collection_link": "https://api.launchpad.net/devel/ubuntu/+archive/partner/processors", "require_virtualized": false, "suppress_subscription_notifications": false, "enabled_restricted_processors_collection_link": "https://api.launchpad.net/devel/ubuntu/+archive/partner/enabled_restricted_processors", "publish_debug_symbols": false, "http_etag": "\"5538dc7e08c40b8f4a70f815ce238dac04523d40-21b4a60342d55dae95fd53a341596f30c8c568dd\"", "self_link": "https://api.launchpad.net/devel/ubuntu/+archive/partner", "resource_type_link": "https://api.launchpad.net/devel/#archive", "status": "Active", "dependencies_collection_link": "https://api.launchpad.net/devel/ubuntu/+archive/partner/dependencies", "authorized_size": null, "displayname": "Partner Archive for Ubuntu", "description": "Partner archive", "permit_obsolete_series_uploads": false, "relative_build_score": 0, "name": "partner", "distribution_link": "https://api.launchpad.net/devel/ubuntu", "web_link": "https://launchpad.net/ubuntu/+archive/partner", "owner_link": "https://api.launchpad.net/devel/~ubuntu-archive", "signing_key_fingerprint": null}], "resource_type_link" : "https://api.launchpad.net/devel/#archive-page-resource"}
diff --git a/test/data/lp/ubuntu.json b/test/data/lp/ubuntu.json
new file mode 100644
index 0000000..180429e
--- /dev/null
+++ b/test/data/lp/ubuntu.json
@@ -0,0 +1 @@
+{"all_specifications_collection_link": "https://api.launchpad.net/devel/ubuntu/all_specifications", "bug_supervisor_link": "https://api.launchpad.net/devel/~ubuntu-bugcontrol", "web_link": "https://launchpad.net/ubuntu", "official_bug_tags": ["a11y", "bisect-done", "bitesize", "cherry-pick", "compat-wireless", "ftbfs", "gnome3", "hibernate", "hw-specific", "kernel-bug", "manpage", "metabug", "multiarch", "needs-bisect", "needs-design", "needs-packaging", "needs-reassignment", "packaging", "patch", "patch-accepted-debian", "patch-accepted-upstream", "patch-forwarded-debian", "patch-forwarded-upstream", "patch-needswork", "patch-rejected", "patch-rejected-debian", "patch-rejected-upstream", "performing-bisect", "precise", "regression-proposed", "regression-release", "regression-update", "resume", "string-fix", "suspend", "systemd-boot", "testcase", "touch", "trusty", "upgrade-software-version", "verification-done", "verification-failed", "verification-needed", "vivid", "wily", "xenial"], "active_milestones_collection_link": "https://api.launchpad.net/devel/ubuntu/active_milestones", "supports_mirrors": true, "main_archive_link": "https://api.launchpad.net/devel/ubuntu/+archive/primary", "icon_link": "https://api.launchpad.net/devel/ubuntu/icon", "all_milestones_collection_link": "https://api.launchpad.net/devel/ubuntu/all_milestones", "cdimage_mirrors_collection_link": "https://api.launchpad.net/devel/ubuntu/cdimage_mirrors", "bug_reported_acknowledgement": "Thank you for spending your time helping to make Ubuntu better with this bug report.  Reporting a bug is the first step in the bug fixing process.  As a part of that process you may need to answer some questions to help developers work on your bug.  You can learn more about how we triage bug reports at http://wiki.ubuntu.com/Bugs/HowToTriage.
", "display_name": "Ubuntu", "mirror_admin_link": "https://api.launchpad.net/devel/~ubuntu-mirror-admins", "title": "Ubuntu", "official_packages": true, "members_link": "https://api.launchpad.net/devel/~ubuntumembers", "domain_name": "ubuntu.com", "archives_collection_link": "https://api.launchpad.net/devel/ubuntu/archives", "http_etag": "\"1fad5a1a660af2192b707b7f31bdd80988a032f6-04db509b6ddc69fac94669bbc31b28dfc6e734a5\"", "vcs": null, "branch_sharing_policy": "Public", "self_link": "https://api.launchpad.net/devel/ubuntu", "current_series_link": "https://api.launchpad.net/devel/ubuntu/xenial", "resource_type_link": "https://api.launchpad.net/devel/#distribution", "translations_usage": "Launchpad", "description": "Ubuntu also includes a wide variety of software through its network of software repositories. Once your system is installed you can simply call up a list of all the existing tools out there and choose any of them for immediate installation over the internet.
", "archive_mirrors_collection_link": "https://api.launchpad.net/devel/ubuntu/archive_mirrors", "translationpermission": "Restricted", "valid_specifications_collection_link": "https://api.launchpad.net/devel/ubuntu/valid_specifications", "redirect_release_uploads": true, "bug_reporting_guidelines": "Are you uncertain if your issue is really a bug?  Then ask a support question about Ubuntu at http://answers.launchpad.net/ubuntu/ - these can be made into bugs later.  Another support venue is http://askubuntu.com.

If you are certain this is a bug please include the source package the bug is in.  For help see https://wiki.ubuntu.com/Bugs/FindRightPackage.

We also need:

1) The release of Ubuntu you are using, via 'lsb_release -rd' or System -\u003e About Ubuntu
2) The version of the package you are using, via 'apt-cache policy pkgname' or by checking in Software Center
3) What you expected to happen
4) What happened instead

Most of this information is gathered when you use apport to report the bug. See https://help.ubuntu.com/community/ReportingBugs for complete details.

The Ubuntu community has also created debugging procedures for a wide variety of packages at https://wiki.ubuntu.com/DebuggingProcedures.  Following the debugging instructions for the affected package will make your bug report much more complete. Thanks!", "active": true, "specification_sharing_policy": "Public", "name": "ubuntu", "driver_link": "https://api.launchpad.net/devel/~ubuntu-drivers", "development_series_alias": "devel", "registrant_link": "https://api.launchpad.net/devel/~techboard", "supports_ppas": true, "summary": "Ubuntu is a complete Linux-based operating system, freely available with both community and professional support.", "mugshot_link": "https://api.launchpad.net/devel/ubuntu/mugshot", "logo_link": "https://api.launchpad.net/devel/ubuntu/logo", "owner_link": "https://api.launchpad.net/devel/~techboard", "translationgroup_link": "https://api.launchpad.net/devel/+groups/ubuntu-translators", "bug_sharing_policy": "Public", "date_created": "2005-12-31T23:59:51+00:00", "homepage_content": null, "series_collection_link": "https://api.launchpad.net/devel/ubuntu/series", "derivatives_collection_link": "https://api.launchpad.net/devel/ubuntu/derivatives"} 
diff --git a/test/test_lp.rb b/test/test_lp.rb
index c754e9a..cc65503 100644
--- a/test/test_lp.rb
+++ b/test/test_lp.rb
@@ -1,86 +1,291 @@
-require_relative '../lib/lp'
+require 'pathname'
+require 'rack'
+require 'webmock/test_unit'
+
 require_relative 'lib/testcase'
+require_relative '../lib/lp'
 
 class FakeLaunchpad
-    def self.call(env)
-        case env["REQUEST_METHOD"]
-        when "GET"
-            return get(env)
-        end
-        raise "unhandled http method '#{env["REQUEST_METHOD"]}' in FakeLaunchpad"
+  def self.call(env)
+    case env['REQUEST_METHOD']
+    when 'GET'
+      return get(env)
     end
+    faile "unhandled http method '#{env['REQUEST_METHOD']}' in #{self}"
+  end
 
-private
-    def self.get(env)
-        case env["PATH_INFO"]
-        when "/devel/~kubuntu-ci/+archive/ubuntu/unstable"
-            # FIXME: code dup and query is order sensitive
-            case env["QUERY_STRING"]
-            when ""
-                return ['200',
-                        {'Content-Type' => 'application/json'},
-                        [json_response("ppa.json")]]
-            when "source_name=kate&ws.op=getPublishedSources"
-                return ['200',
-                        {'Content-Type' => 'application/json'},
-                        [json_response("ppa-sources-kate-1.json")]]
-            when "memo=2&source_name=kate&ws.op=getPublishedSources&ws.size=2&ws.start=2"
-                return ['200',
-                        {'Content-Type' => 'application/json'},
-                        [json_response("ppa-sources-kate-2.json")]]
-            end
-        when "/devel/~kubuntu-ci/+archive/ubuntu/unstable/+sourcepub/4571865"
-            case env["QUERY_STRING"]
-            when "ws.op=changelogUrl"
-                return ['200',
-                        {'Content-Type' => 'application/json'},
-                        ["\"http://foobar\""]]
-            end
-        end
-        raise "unhandled get url '#{env["PATH_INFO"]}?#{env["QUERY_STRING"]}' in FakeLaunchpad"
+  def self.get(env)
+    path = Pathname.new(env['PATH_INFO']).cleanpath.to_s
+    query = env['QUERY_STRING']
+    case path
+    when '/devel/ubuntu'
+      case query
+      when ''
+        return ['200',
+                { 'Content-Type' => 'application/json' },
+                [json_response('ubuntu.json')]]
+      when 'ws.op=yolokittenstein'
+        return ['400', {}, []]
+      when 'archive=https://api.launchpad.net/devel/ubuntu/%2Barchive/primary&ws.op=GetYoloKitten'
+        return ['200', {}, ['{"yolo_kitten":"kitten"}']]
+      end
+    when '/devel/ubuntu/archives'
+      # NOTE: this implements a linked list. Queries can returned limited
+      #   collections which point to the next part of the collection which must
+      #   be queried independently.
+      case query
+      when '', 'memo=1&ws.size=1&ws.start=1'
+        set = '1'
+        set = '2' if query == 'memo=1&ws.size=1&ws.start=1'
+        return ['200',
+                { 'Content-Type' => 'application/json' },
+                [json_response("ubuntu-archives#{set}.json")]]
+      end
+    when '/devel/ubuntu/+archive/primary'
+      return ['200',
+              { 'Content-Type' => 'application/json' },
+              [json_response('ubuntu-archive-primary.json')]]
+    when '/devel/~kubuntu-ci/+archive/ubuntu/unstable'
+      # FIXME: code dup and query is order sensitive
+      case env['QUERY_STRING']
+      when ''
+        return ['200',
+                { 'Content-Type' => 'application/json' },
+                [json_response('ppa.json')]]
+      when 'source_name=kate&ws.op=getPublishedSources'
+        return ['200',
+                { 'Content-Type' => 'application/json' },
+                [json_response('ppa-sources-kate-1.json')]]
+      when 'memo=2&source_name=kate&ws.op=getPublishedSources&ws.size=2&ws.start=2'
+        return ['200',
+                { 'Content-Type' => 'application/json' },
+                [json_response('ppa-sources-kate-2.json')]]
+      end
+    when '/devel/~kubuntu-ci/+archive/ubuntu/unstable/+sourcepub/4571865'
+      case env['QUERY_STRING']
+      when 'ws.op=changelogUrl'
+        return ['200',
+                { 'Content-Type' => 'application/json' },
+                ["\"http://foobar\""]]
+      end
     end
+    fail "unhandled get '#{path}?#{env['QUERY_STRING']}' in #{self}"
+  end
 
-    def self.json_response(file_name)
-      File.open("#{__dir__}/data/lp/#{file_name}").read
-    end
+  def self.json_response(file_name)
+    # FIXME: use @datadir or something
+    File.open("#{__dir__}/data/lp/#{file_name}").read
+  end
 end
 
+# Test launchpad
 class LaunchpadTest < TestCase
   def setup
-    Launchpad.instance_variable_set(:@conf_path, '/tmp')
+    WebMock.disable_net_connect!(allow_localhost: true)
+
+    @oauth_token = 'accesskey'
+    @oauth_token_secret = 'accesssecret'
+    @oauth_params = {
+      'oauth_consumer_key' => 'kubuntu-ci',
+      'oauth_signature' => "&#{@oauth_token_secret}",
+      'oauth_signature_method' => 'PLAINTEXT',
+      'oauth_token' => @oauth_token
+    }
+    @token_json ||= File.read(@datadir + '/token.json')
+
+    Launchpad.instance_variable_set(:@io_retry_sleeps, 0)
+    Launchpad.instance_variable_set(:@conf_path, Dir.pwd)
+
+    conf = "#{Dir.pwd}/.config"
+    FileUtils.mkpath(conf)
+    File.write("#{conf}/lp-tokens.json", @token_json)
+  end
+
+  def teardown
+    Launchpad.instance_variable_set(:@conf_path, Dir.home)
+  end
+
+  # Helper to redirect stdin so we can simulate user input as authentication
+  # prompts for 'done' once authorization was granted on launchpad.
+  def stdinit
+    stdin = $stdin
+    $stdin, input = IO.pipe
+    yield input
+  ensure
+    input.close
+    $stdin = stdin
+  end
+
+  def valid_auth?(request)
+    headers = request.headers
+    return false unless headers.include?('Authorization')
+    params = OAuth::Helper.parse_header(headers['Authorization'])
+    params.dup.merge(@oauth_params) == params
   end
 
   def test_token
-    assert_equal(Launchpad.token, nil)
+    token = Launchpad.token
+    assert_not_nil(token, 'token was nil')
+    assert_is_a(token, OAuth::AccessToken)
   end
 
-  # FIXME: need auth test
+  def test_authenticate
+    FileUtils.rm_r('.config')
+    token = nil
+    # Request token stub
+    request_response = 'oauth_token=requestkey&oauth_token_secret=requestsecret'
+    stub_request(:post, 'https://launchpad.net/+request-token')
+      .to_return(body: request_response)
+    # Access token stub
+    token_request = {
+      'oauth_consumer_key' => 'kubuntu-ci',
+      'oauth_signature' => '&requestsecret',
+      'oauth_signature_method' => 'PLAINTEXT',
+      'oauth_token' => 'requestkey'
+    }
+    access_response = "oauth_token=#{@oauth_token}" \
+                      "&oauth_token_secret=#{@oauth_token_secret}"
+    stub_request(:post, 'https://launchpad.net/+access-token')
+      .with(body: hash_including(token_request))
+      .to_return(body: access_response)
+
+    stdinit do |input|
+      input.puts 'done'
+      token = Launchpad.authenticate
+    end
+
+    assert_not_nil(token, 'token was nil')
+    assert_is_a(token, OAuth::AccessToken)
+    assert_equal(@oauth_token, token.token)
+    assert_equal(@oauth_token_secret, token.secret)
+    assert_equal(JSON.parse(@token_json),
+                 JSON.parse(File.read('.config/lp-tokens.json')))
+  end
+
+  def test_get_through_token
+    stub_request(:get, "https://api.launchpad.net/#{__method__}")
+      .with { |r| valid_auth?(r) }
+      .to_return(status: 200, body: '', headers: {})
+    assert_not_nil(Launchpad.token)
+
+    Launchpad.get(URI("https://api.launchpad.net/#{__method__}"))
+
+    assert_requested(:get, "https://api.launchpad.net/#{__method__}", times: 1)
+  end
+
+  def test_get
+    # Need not have a valid token here as we want to have a get without Auth
+    FileUtils.rm_r('.config')
+    assert_nil(Launchpad.token)
+    stub_request(:get, "https://api.launchpad.net/#{__method__}")
+      .with { |request| next !request.headers.include?('Authorization') }
+      .to_return(status: 200, body: '', headers: {})
+
+    Launchpad.get(URI("https://api.launchpad.net/#{__method__}"))
+
+    assert_requested(:get, "https://api.launchpad.net/#{__method__}", times: 1)
+  end
+
+  def test_get_network_error
+    stub_request(:get, "https://api.launchpad.net/#{__method__}")
+      .to_return(status: 401, body: '', headers: {})
+
+    assert_raise Net::HTTPRetriableError do
+      Launchpad.get(URI("https://api.launchpad.net/#{__method__}"))
+    end
+
+    assert_requested(:get, "https://api.launchpad.net/#{__method__}",
+                     times: Launchpad::IO_RETRIES)
+  end
+
+  def test_post_through_token_has_auth
+    assert_not_nil(Launchpad.token)
+    stub_request(:post, "https://api.launchpad.net/#{__method__}")
+      .with { |r| valid_auth?(r) }
+      .to_return(status: 200, body: '', headers: {})
+
+    Launchpad.post(URI("https://api.launchpad.net/#{__method__}"))
+
+    assert_requested(:post, "https://api.launchpad.net/#{__method__}", times: 1)
+  end
+
+  def test_post_through_token_carries_query
+    stub_request(:post, "https://api.launchpad.net/#{__method__}")
+      .with(body: 'a=a1&b=b1')
+      .to_return(status: 200, body: '', headers: {})
+
+    Launchpad.post(URI("https://api.launchpad.net/#{__method__}?a=a1&b=b1"))
+
+    assert_requested(:post, "https://api.launchpad.net/#{__method__}", times: 1)
+  end
+
+  def test_post
+    # Posting without token causes runtime errors.
+    FileUtils.rm_r('.config')
+    stub_request(:post, "https://api.launchpad.net/#{__method__}")
+      .to_return(status: 401, body: '', headers: {})
+
+    assert_raise RuntimeError do
+      Launchpad.post(URI("https://api.launchpad.net/#{__method__}"))
+    end
+
+    assert_not_requested(:post, "https://api.launchpad.net/#{__method__}",
+                         times: 1)
+  end
+
+  def test_post_network_error
+    stub_request(:post, "https://api.launchpad.net/#{__method__}")
+      .to_return(status: 401, body: '', headers: {})
+
+    assert_raise Net::HTTPRetriableError do
+      Launchpad.post(URI("https://api.launchpad.net/#{__method__}"))
+    end
+
+    assert_requested(:post, "https://api.launchpad.net/#{__method__}",
+                     times: Launchpad::IO_RETRIES)
+  end
 end
 
 class LaunchpadRubberTest < TestCase
   def setup
-    Launchpad.instance_variable_set(:@conf_path, '/tmp')
+    Launchpad.instance_variable_set(:@conf_path, Dir.pwd)
 
-    # TODO: make mock optional
-    require 'webmock/test_unit'
-    require 'rack'
     WebMock.disable_net_connect!(allow_localhost: true)
     stub_request(:any, /api.launchpad.net/).to_rack(FakeLaunchpad)
 
-    ppa_url = 'https://api.launchpad.net/devel/~kubuntu-ci/+archive/ubuntu/unstable'
-    @ppa = Launchpad::Rubber.from_url(ppa_url)
-    assert(@ppa)
+    @ppa_path = '~kubuntu-ci/+archive/ubuntu/unstable'
+    @ppa_url = "https://api.launchpad.net/devel/#{@ppa_path}"
+  end
+
+  def teardown
+    assert_equal(Launchpad.token, nil)
+  end
+
+  def test_from_url
+    ppa = Launchpad::Rubber.from_url(@ppa_url)
+    assert(ppa)
     # Has a bunch of properties]
-    assert_equal(@ppa.status, 'Active')
-    assert_equal(@ppa.name, 'unstable')
-    assert_equal(@ppa.self_link, ppa_url)
+    assert_equal('Active', ppa.status)
+    assert_equal('unstable', ppa.name)
+    assert_equal(@ppa_url, ppa.self_link)
   end
 
-  # TODO: test from_json
-  # TODO: maybe test get and post directly?
+  def test_from_path
+    ppa = Launchpad::Rubber.from_path(@ppa_path)
+    devel = Launchpad::Rubber.from_path("devel/#{@ppa_path}")
+    slashdevel = Launchpad::Rubber.from_path("/devel/#{@ppa_path}")
+    assert(ppa)
+    # Has a bunch of properties]
+    assert_equal('Active', ppa.status)
+    assert_equal('unstable', ppa.name)
+    assert_equal(@ppa_url, ppa.self_link)
+    assert_equal(ppa, devel)
+    assert_equal(ppa, slashdevel)
+  end
 
   def test_ppa_source_collection
-    sources = @ppa.getPublishedSources(source_name: "kate")
+    ppa = Launchpad::Rubber.from_url(@ppa_url)
+    sources = ppa.getPublishedSources(source_name: 'kate')
     assert_not_nil(sources)
     # TODO: when run against live this needs to be >=0
     assert_equal(sources.size, 4)
@@ -93,7 +298,38 @@ class LaunchpadRubberTest < TestCase
       source.status
     end
     # Can GET a string-only variable. This mustn't make the parser trip.
-    assert_respond_to(source.changelogUrl(), :downcase)
-    puts source.changelogUrl()[0]
+    assert_respond_to(source.changelogUrl, :downcase)
+  end
+
+  def test_collection_link
+    ubuntu = Launchpad::Rubber.from_path('ubuntu')
+    archives = ubuntu.archives
+    assert_not_nil(archives)
+    assert_equal(2, archives.size)
+    assert_equal('Primary Archive for Ubuntu', archives[0].displayname)
+    assert_equal('Partner Archive for Ubuntu', archives[1].displayname)
+  end
+
+  def test_missing_link
+    ubuntu = Launchpad::Rubber.from_path('ubuntu')
+    archive = ubuntu.main_archive
+    assert_not_nil(archive)
+    assert_equal('Primary Archive for Ubuntu', archive.displayname)
+  end
+
+  def test_invalid_attribute
+    ubuntu = Launchpad::Rubber.from_path('ubuntu')
+    assert_raise Net::HTTPRetriableError do
+      ubuntu.yolokittenstein
+    end
+  end
+
+  def test_build_params_self_link
+    ubuntu = Launchpad::Rubber.from_path('ubuntu')
+    archive = ubuntu.main_archive
+    r = ubuntu.GetYoloKitten(archive: archive)
+    assert_not_nil(r)
+    assert(r.respond_to?(:yolo_kitten))
+    assert_equal('kitten', r.yolo_kitten)
   end
 end

-- 
ci-tooling packaging



More information about the pkg-kde-commits mailing list