This is also failing for me when I run the entire mvn install (after a mvn clean).. it's not just on the CI for me
On Sep 25, 2014, at 2:20 PM, Robbie Gemmell <robbie.gemm...@gmail.com> wrote: > Failing in a different way now, the overall run of the python tests bombs > out. I see the same thing locally, where it was working when I made the > commit immediately before yours :) > > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/683/console > > Running org.apache.qpid.proton.JythonTest > Sep 25, 2014 6:03:44 PM org.apache.qpid.proton.JythonTest test > INFO: About to call Jython test script: > '/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test' > with '/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python' > added to Jython path > Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 7.714 > sec <<< FAILURE! > test(org.apache.qpid.proton.JythonTest) Time elapsed: 7.675 sec <<< FAILURE! > java.lang.AssertionError: Caught PyException on invocation number 2: > Traceback (most recent call last): > File > "/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test", > line 597, in <module> > h.scan(m) > File > "/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test", > line 587, in scan > if not (child in self.scanned or child in objects): > TypeError: object of type 'object' has no len() > with message: null > at org.junit.Assert.fail(Assert.java:93) > at org.apache.qpid.proton.JythonTest.runTestOnce(JythonTest.java:120) > at org.apache.qpid.proton.JythonTest.test(JythonTest.java:95) > > > On 25 September 2014 18:59, Alan Conway <acon...@redhat.com> wrote: > >> On Thu, 2014-09-25 at 15:59 +0100, Robbie Gemmell wrote: >>> On 25 September 2014 15:00, Alan Conway <acon...@redhat.com> wrote: >>> >>>> On Wed, 2014-09-24 at 12:19 +0100, Robbie Gemmell wrote: >>>>> The tests are now running again, but a couple of the URL tests still >> seem >>>>> to be failing on the CI job: >>>>> >>>> >> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/ >>>>> >>>> >>>> They are all failing with: >>>> Not a valid port number or service name: 'amqps' >>>> >>>> Could this be a configuration problem on the CI machine, i.e. missing >> an >>>> 'amqps' entry in /etc/services? Can I get access to the CI machine to >>>> poke around and see what's up? >>>> >>> >>> Almost certainly no, only the core maintainers are allowed shell access >> as >>> far as I've seen. You can ask on bui...@apache.org for those with >> access to >>> check things out and report back and see what happens. >>> >>> I think the CI instances will be running Ubuntu 12.04 or 14.04 LTS. For >>> giggles, I dug out an ooooold Ubuntu VM with Java 6 on it and tried the >>> tests, which failed, and it indeed has no amqp[s] entry in /etc/services >>> file so that could well be it. >> >> Thanks for checking that out! I have hacked the tests to skip tests for >> 'amqps' if it is not recognized. Poke me if there are still failures. >> >> ------------------------------------------------------------------------ >> r1627577 | aconway | 2014-09-25 13:59:17 -0400 (Thu, 25 Sep 2014) | 5 >> lines >> >> NO-JIRA: Fix URL test to skip 'amqps' tests if 'amqps' is not recognized >> as a service name. >> >> On some older Ubuntu with Java 6, 'amqps' is not recognized as a service >> name so >> skip those tests in that case. >> >> ------------------------------------------------------------------------ >> >>>> >>>> The URL code uses socket.getservbyname() to look up service names. Is >>>> there a more portable way to do it? >>>> >>> >>> No idea I'm afraid. >>> >>> >>>> >>>> Cheers, >>>> Alan. >>>> >>>>> As mentioned in my other post about a timeline for dropping Java6 >>>> support, >>>>> they seem to work on Java8 (havent tried Java7). >>>>> >>>>> Robbie >>>>> >>>>> On 22 September 2014 21:14, Alan Conway <acon...@redhat.com> wrote: >>>>> >>>>>> My bad, didn't run the java tests. Will fix ASAP and then give >> myself a >>>>>> flogging. >>>>>> >>>>>> On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote: >>>>>>> This seems to have broken the Java test runs: >>>>>>> >>>>>>> >> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/ >>>>>>> >>>>>>> >>>>>>> >>>>>>> On 19 September 2014 22:00, <acon...@apache.org> wrote: >>>>>>> >>>>>>>> Author: aconway >>>>>>>> Date: Fri Sep 19 21:00:50 2014 >>>>>>>> New Revision: 1626329 >>>>>>>> >>>>>>>> URL: http://svn.apache.org/r1626329 >>>>>>>> Log: >>>>>>>> PROTON-693: Python Url class to wrap C function pni_parse_url >>>>>>>> >>>>>>>> It was pointed out that pni_parse_url is an internal function >> and >>>> the >>>>>>>> interface >>>>>>>> is not suitable for public API. >>>>>>>> >>>>>>>> Rewrote the URL parser as a proper swigable C API pn_url_*. >> This >>>> gets >>>>>> rid >>>>>>>> of the >>>>>>>> need for previous swig insanity and is cleaner all round. >>>>>>>> >>>>>>>> Internally still uses the pni_parse_url parser, we can clean >> that >>>> up >>>>>> later. >>>>>>>> >>>>>>>> Added: >>>>>>>> qpid/proton/trunk/proton-c/include/proton/url.h >>>>>>>> qpid/proton/trunk/proton-c/src/url.c >>>>>>>> Modified: >>>>>>>> qpid/proton/trunk/proton-c/CMakeLists.txt >>>>>>>> qpid/proton/trunk/proton-c/bindings/perl/perl.i >>>>>>>> qpid/proton/trunk/proton-c/bindings/php/php.i >>>>>>>> qpid/proton/trunk/proton-c/bindings/python/cproton.i >>>>>>>> qpid/proton/trunk/proton-c/bindings/python/proton.py >>>>>>>> qpid/proton/trunk/proton-c/bindings/ruby/ruby.i >>>>>>>> qpid/proton/trunk/proton-c/include/proton/cproton.i >>>>>>>> qpid/proton/trunk/tests/python/proton_tests/url.py >>>>>>>> >>>>>>>> Modified: qpid/proton/trunk/proton-c/CMakeLists.txt >>>>>>>> URL: >>>>>>>> >>>>>> >>>> >> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff >>>>>>>> >>>>>>>> >>>>>> >>>> >> ============================================================================== >>>>>>>> --- qpid/proton/trunk/proton-c/CMakeLists.txt (original) >>>>>>>> +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19 >> 21:00:50 >>>> 2014 >>>>>>>> @@ -270,6 +270,7 @@ set (qpid-proton-core >>>>>>>> src/object/iterator.c >>>>>>>> >>>>>>>> src/util.c >>>>>>>> + src/url.c >>>>>>>> src/error.c >>>>>>>> src/buffer.c >>>>>>>> src/parser.c >>>>>>>> >>>>>>>> Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i >>>>>>>> URL: >>>>>>>> >>>>>> >>>> >> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff >>>>>>>> >>>>>>>> >>>>>> >>>> >> ============================================================================== >>>>>>>> --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original) >>>>>>>> +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19 >>>> 21:00:50 >>>>>>>> 2014 >>>>>>>> @@ -8,6 +8,7 @@ >>>>>>>> #include <proton/messenger.h> >>>>>>>> #include <proton/ssl.h> >>>>>>>> #include <proton/driver_extras.h> >>>>>>>> +#include <proton/url.h> >>>>>>>> %} >>>>>>>> >>>>>>>> %include <cstring.i> >>>>>>>> >>>>>>>> Modified: qpid/proton/trunk/proton-c/bindings/php/php.i >>>>>>>> URL: >>>>>>>> >>>>>> >>>> >> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff >>>>>>>> >>>>>>>> >>>>>> >>>> >> ============================================================================== >>>>>>>> --- qpid/proton/trunk/proton-c/bindings/php/php.i (original) >>>>>>>> +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19 >>>> 21:00:50 >>>>>> 2014 >>>>>>>> @@ -29,6 +29,7 @@ >>>>>>>> %header %{ >>>>>>>> /* Include the headers needed by the code in this wrapper >> file */ >>>>>>>> #include <proton/types.h> >>>>>>>> +#include <proton/url.h> >>>>>>>> #include <proton/message.h> >>>>>>>> #include <proton/driver.h> >>>>>>>> #include <proton/driver_extras.h> >>>>>>>> >>>>>>>> Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i >>>>>>>> URL: >>>>>>>> >>>>>> >>>> >> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff >>>>>>>> >>>>>>>> >>>>>> >>>> >> ============================================================================== >>>>>>>> --- qpid/proton/trunk/proton-c/bindings/python/cproton.i >> (original) >>>>>>>> +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri >> Sep 19 >>>>>>>> 21:00:50 2014 >>>>>>>> @@ -23,6 +23,7 @@ >>>>>>>> #include <winsock2.h> >>>>>>>> #endif >>>>>>>> #include <proton/engine.h> >>>>>>>> +#include <proton/url.h> >>>>>>>> #include <proton/message.h> >>>>>>>> #include <proton/sasl.h> >>>>>>>> #include <proton/driver.h> >>>>>>>> @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s >>>>>>>> } >>>>>>>> %} >>>>>>>> >>>>>>>> - >>>>>>>> -/** >>>>>>>> - pni_parse_url(char* url, char **scheme, char **user, char >>>> **pass, >>>>>> char >>>>>>>> **host, char **port, char **path) >>>>>>>> - The following type maps convert this into a python function >>>> that >>>>>> taks >>>>>>>> a URL string argument >>>>>>>> - and returns a list of strings [scheme, user, pass, host, >> port, >>>>>> path] >>>>>>>> - This probably could be done more neatly. >>>>>>>> -*/ >>>>>>>> - >>>>>>>> -// Typemap to copy the url string as it will be modified by >>>> parse_url >>>>>>>> -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char >> *url >>>> (int >>>>>>>> res, char *t = 0, size_t n = 0, int alloc = 0) { >>>>>>>> - res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc); >>>>>>>> - if (!SWIG_IsOK(res)) { >>>>>>>> - %argument_fail(res, "char *url", $symname, $argnum); >>>>>>>> - } >>>>>>>> - $1 = %new_array(n, $*1_ltype); >>>>>>>> - memcpy($1,t,sizeof(char)*n); >>>>>>>> - if (alloc == SWIG_NEWOBJ) %delete_array(t); >>>>>>>> - $1[n-1] = 0; >>>>>>>> -} >>>>>>>> -%typemap(freearg,match="in") char *url "free($1);"; >>>>>>>> -%typemap(argout) char *url ""; >>>>>>>> - >>>>>>>> -// Typemap for char** return strings. Don't free them. >>>>>>>> -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0) >> "$1 = >>>>>> &temp;"; >>>>>>>> -%typemap(freearg,match="in") char **OUTSTR ""; >>>>>>>> -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char >>>> **OUTSTR { >>>>>>>> - %append_output(SWIG_FromCharPtr(*$1)); >>>>>>>> -} >>>>>>>> - >>>>>>>> -// Typemap to initialize result as empty list >>>>>>>> -%typemap(out) void "$result = PyList_New(0);"; >>>>>>>> - >>>>>>>> - >>>>>>>> -%apply char** OUTSTR {char **scheme, char **user, char **pass, >>>> char >>>>>>>> **host, char **port, char **path}; >>>>>>>> -void pni_parse_url(char* url, char **scheme, char **user, char >>>> **pass, >>>>>>>> char **host, char **port, char **path); >>>>>>>> -%ignore pni_parse_url; >>>>>>>> - >>>>>>>> %include "proton/cproton.i" >>>>>>>> >>>>>>>> Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py >>>>>>>> URL: >>>>>>>> >>>>>> >>>> >> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff >>>>>>>> >>>>>>>> >>>>>> >>>> >> ============================================================================== >>>>>>>> --- qpid/proton/trunk/proton-c/bindings/python/proton.py >> (original) >>>>>>>> +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri >> Sep 19 >>>>>>>> 21:00:50 2014 >>>>>>>> @@ -3657,114 +3657,98 @@ __all__ = [ >>>>>>>> >>>>>>>> >>>>>>>> class Url(object): >>>>>>>> - """ >>>>>>>> - Simple URL parser/constructor, handles URLs of the form: >>>>>>>> + """ >>>>>>>> + Simple URL parser/constructor, handles URLs of the form: >>>>>>>> >>>>>>>> - <scheme>://<user>:<password>@<host>:<port>/<path> >>>>>>>> + <scheme>://<user>:<password>@<host>:<port>/<path> >>>>>>>> >>>>>>>> - All components can be None if not specifeid in the URL >> string. >>>>>>>> + All components can be None if not specifeid in the URL >> string. >>>>>>>> >>>>>>>> - The port can be specified as a service name, e.g. 'amqp' >> in >>>> the >>>>>>>> - URL string but Url.port always gives the integer value. >>>>>>>> + The port can be specified as a service name, e.g. 'amqp' in >> the >>>>>>>> + URL string but Url.port always gives the integer value. >>>>>>>> + >>>>>>>> + @ivar scheme: Url scheme e.g. 'amqp' or 'amqps' >>>>>>>> + @ivar user: Username >>>>>>>> + @ivar password: Password >>>>>>>> + @ivar host: Host name, ipv6 literal or ipv4 dotted quad. >>>>>>>> + @ivar port: Integer port. >>>>>>>> + @ivar host_port: Returns host:port >>>>>>>> + """ >>>>>>>> + >>>>>>>> + AMQPS = "amqps" >>>>>>>> + AMQP = "amqp" >>>>>>>> + >>>>>>>> + class Port(int): >>>>>>>> + """An integer port number that can be constructed from a >>>> service >>>>>> name >>>>>>>> string""" >>>>>>>> + >>>>>>>> + def __new__(cls, value): >>>>>>>> + port = super(Url.Port, cls).__new__(cls, >>>> cls.port_int(value)) >>>>>>>> + setattr(port, 'name', str(value)) >>>>>>>> + return port >>>>>>>> + >>>>>>>> + def __eq__(self, x): return str(self) == x or int(self) >> == x >>>>>>>> + def __ne__(self, x): return not self == x >>>>>>>> + def __str__(self): return str(self.name) >>>>>>>> + >>>>>>>> + @staticmethod >>>>>>>> + def port_int(value): >>>>>>>> + """Convert service, an integer or a service name, into >> an >>>>>> integer >>>>>>>> port number.""" >>>>>>>> + try: >>>>>>>> + return int(value) >>>>>>>> + except ValueError: >>>>>>>> + try: >>>>>>>> + return socket.getservbyname(value) >>>>>>>> + except socket.error: >>>>>>>> + raise ValueError("Not a valid port number or service >>>> name: >>>>>>>> '%s'" % value) >>>>>>>> >>>>>>>> - @ivar scheme: Url scheme e.g. 'amqp' or 'amqps' >>>>>>>> - @ivar user: Username >>>>>>>> - @ivar password: Password >>>>>>>> - @ivar host: Host name, ipv6 literal or ipv4 dotted quad. >>>>>>>> - @ivar port: Integer port. >>>>>>>> - @ivar host_port: Returns host:port >>>>>>>> + def __init__(self, url=None, **kwargs): >>>>>>>> + """ >>>>>>>> + @param url: URL string to parse. >>>>>>>> + @param kwargs: scheme, user, password, host, port, path. >>>>>>>> + If specified, replaces corresponding part in url string. >>>>>>>> """ >>>>>>>> + if url: >>>>>>>> + self._url = pn_url_parse(str(url)) >>>>>>>> + if not self._url: raise ValueError("Invalid URL '%s'" % >> url) >>>>>>>> + else: >>>>>>>> + self._url = pn_url() >>>>>>>> + for k in kwargs: # Let kwargs override values >>>> parsed >>>>>> from >>>>>>>> url >>>>>>>> + getattr(self, k) # Check for invalid kwargs >>>>>>>> + setattr(self, k, kwargs[k]) >>>>>>>> + >>>>>>>> + class PartDescriptor(object): >>>>>>>> + def __init__(self, part): >>>>>>>> + self.getter = globals()["pn_url_%s" % part] >>>>>>>> + self.setter = globals()["pn_url_set_%s" % part] >>>>>>>> + def __get__(self, obj, type=None): return >>>> self.getter(obj._url) >>>>>>>> + def __set__(self, obj, value): return >> self.setter(obj._url, >>>>>>>> str(value)) >>>>>>>> + >>>>>>>> + scheme = PartDescriptor('scheme') >>>>>>>> + username = PartDescriptor('username') >>>>>>>> + password = PartDescriptor('password') >>>>>>>> + host = PartDescriptor('host') >>>>>>>> + path = PartDescriptor('path') >>>>>>>> + >>>>>>>> + @property >>>>>>>> + def port(self): >>>>>>>> + portstr = pn_url_port(self._url) >>>>>>>> + return portstr and Url.Port(portstr) >>>>>>>> + >>>>>>>> + @port.setter >>>>>>>> + def port(self, value): >>>>>>>> + if value is None: pn_url_set_port(self._url, None) >>>>>>>> + else: pn_url_set_port(self._url, str(Url.Port(value))) >>>>>>>> >>>>>>>> - AMQPS = "amqps" >>>>>>>> - AMQP = "amqp" >>>>>>>> + def __str__(self): return pn_url_str(self._url) >>>>>>>> >>>>>>>> - class Port(int): >>>>>>>> - """An integer port number that can also have an >> associated >>>>>> service >>>>>>>> name string""" >>>>>>>> + def __repr__(self): return "Url(%r)" % str(self) >>>>>>>> >>>>>>>> - def __new__(cls, value): >>>>>>>> - port = super(Url.Port, cls).__new__(cls, >>>> cls.port_int(value)) >>>>>>>> - setattr(port, 'name', str(value)) >>>>>>>> - return port >>>>>>>> - >>>>>>>> - def __eq__(self, x): return str(self) == x or int(self) >> == x >>>>>>>> - def __ne__(self, x): return not self == x >>>>>>>> - def __str__(self): return str(self.name) >>>>>>>> - >>>>>>>> - @staticmethod >>>>>>>> - def port_int(value): >>>>>>>> - """Convert service, an integer or a service name, >> into an >>>>>> integer >>>>>>>> port number.""" >>>>>>>> - try: >>>>>>>> - return int(value) >>>>>>>> - except ValueError: >>>>>>>> - try: >>>>>>>> - return socket.getservbyname(value) >>>>>>>> - except socket.error: >>>>>>>> - raise ValueError("Not a valid port number or >> service >>>> name: >>>>>>>> '%s'" % value) >>>>>>>> - >>>>>>>> - def __init__(self, url=None, **kwargs): >>>>>>>> - """ >>>>>>>> - @param url: String or Url instance to parse or copy. >>>>>>>> - @param kwargs: URL fields: scheme, user, password, >> host, >>>> port, >>>>>>>> path. >>>>>>>> - If specified, replaces corresponding component in >> url. >>>>>>>> - """ >>>>>>>> - >>>>>>>> - fields = ['scheme', 'user', 'password', 'host', >> 'port', >>>>>> 'path'] >>>>>>>> - >>>>>>>> - for f in fields: setattr(self, f, None) >>>>>>>> - for k in kwargs: getattr(self, k) # Check for invalid >>>> kwargs >>>>>>>> - >>>>>>>> - if isinstance(url, Url): # Copy from another Url >> instance. >>>>>>>> - self.__dict__.update(url.__dict__) >>>>>>>> - elif url is not None: # Parse from url >>>>>>>> - parts = pni_parse_url(str(url)) >>>>>>>> - if not filter(None, parts): raise >> ValueError("Invalid >>>> AMQP >>>>>>>> URL: '%s'" % url) >>>>>>>> - self.scheme, self.user, self.password, self.host, >>>> port, >>>>>>>> self.path = parts >>>>>>>> - if not self.host: self.host = None >>>>>>>> - self.port = port and self.Port(port) >>>>>>>> - >>>>>>>> - # Let kwargs override values previously set from url >>>>>>>> - for field in fields: >>>>>>>> - setattr(self, field, kwargs.get(field, >> getattr(self, >>>>>> field))) >>>>>>>> - >>>>>>>> - def __repr__(self): >>>>>>>> - return "Url(%r)" % str(self) >>>>>>>> - >>>>>>>> - def __str__(self): >>>>>>>> - s = "" >>>>>>>> - if self.scheme: >>>>>>>> - s += "%s://" % self.scheme >>>>>>>> - if self.user: >>>>>>>> - s += self.user >>>>>>>> - if self.password: >>>>>>>> - s += ":%s" % self.password >>>>>>>> - if self.user or self.password: >>>>>>>> - s += '@' >>>>>>>> - if self.host and ':' in self.host: >>>>>>>> - s += "[%s]" % self.host >>>>>>>> - elif self.host: >>>>>>>> - s += self.host >>>>>>>> - if self.port: >>>>>>>> - s += ":%s" % self.port >>>>>>>> - if self.path: >>>>>>>> - s += "/%s" % self.path >>>>>>>> - return s >>>>>>>> - >>>>>>>> - def __eq__(self, url): >>>>>>>> - return \ >>>>>>>> - self.scheme == url.scheme and \ >>>>>>>> - self.user == url.user and self.password == >>>> url.password >>>>>> and \ >>>>>>>> - self.host == url.host and self.port == url.port >> and \ >>>>>>>> - self.path == url.path >>>>>>>> - >>>>>>>> - def __ne__(self, url): >>>>>>>> - return not self.__eq__(url) >>>>>>>> - >>>>>>>> - def defaults(self): >>>>>>>> - """ >>>>>>>> - Fill in missing values with defaults >>>>>>>> - @return: self >>>>>>>> - """ >>>>>>>> - self.scheme = self.scheme or self.AMQP >>>>>>>> - self.host = self.host or '0.0.0.0' >>>>>>>> - self.port = self.port or self.Port(self.scheme) >>>>>>>> - return self >>>>>>>> + def defaults(self): >>>>>>>> + """ >>>>>>>> + Fill in missing values (scheme, host or port) with >> defaults >>>>>>>> + @return: self >>>>>>>> + """ >>>>>>>> + self.scheme = self.scheme or self.AMQP >>>>>>>> + self.host = self.host or '0.0.0.0' >>>>>>>> + self.port = self.port or self.Port(self.scheme) >>>>>>>> + return self >>>>>>>> >>>>>>>> Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i >>>>>>>> URL: >>>>>>>> >>>>>> >>>> >> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff >>>>>>>> >>>>>>>> >>>>>> >>>> >> ============================================================================== >>>>>>>> --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original) >>>>>>>> +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19 >>>> 21:00:50 >>>>>>>> 2014 >>>>>>>> @@ -26,8 +26,8 @@ >>>>>>>> #include <proton/messenger.h> >>>>>>>> #include <proton/ssl.h> >>>>>>>> #include <proton/driver_extras.h> >>>>>>>> - >>>>>>>> #include <proton/types.h> >>>>>>>> +#include <proton/url.h> >>>>>>>> >>>>>>>> #include <uuid/uuid.h> >>>>>>>> %} >>>>>>>> >>>>>>>> Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i >>>>>>>> URL: >>>>>>>> >>>>>> >>>> >> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff >>>>>>>> >>>>>>>> >>>>>> >>>> >> ============================================================================== >>>>>>>> --- qpid/proton/trunk/proton-c/include/proton/cproton.i >> (original) >>>>>>>> +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri >> Sep 19 >>>>>>>> 21:00:50 2014 >>>>>>>> @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t; >>>>>>>> pn_delivery_t *pn_cast_pn_delivery(void *x) { return >>>> (pn_delivery_t >>>>>> *) >>>>>>>> x; } >>>>>>>> pn_transport_t *pn_cast_pn_transport(void *x) { return >>>>>> (pn_transport_t >>>>>>>> *) x; } >>>>>>>> %} >>>>>>>> + >>>>>>>> +%include "proton/url.h" >>>>>>>> + >>>>>>>> >>>>>>>> Added: qpid/proton/trunk/proton-c/include/proton/url.h >>>>>>>> URL: >>>>>>>> >>>>>> >>>> >> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto >>>>>>>> >>>>>>>> >>>>>> >>>> >> ============================================================================== >>>>>>>> --- qpid/proton/trunk/proton-c/include/proton/url.h (added) >>>>>>>> +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19 >>>> 21:00:50 >>>>>>>> 2014 >>>>>>>> @@ -0,0 +1,83 @@ >>>>>>>> +#ifndef PROTON_URL_H >>>>>>>> +#define PROTON_URL_H >>>>>>>> +/* >>>>>>>> + * Licensed to the Apache Software Foundation (ASF) under one >>>>>>>> + * or more contributor license agreements. See the NOTICE >> file >>>>>>>> + * distributed with this work for additional information >>>>>>>> + * regarding copyright ownership. The ASF licenses this file >>>>>>>> + * to you 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 >>>>>>>> + * >>>>>>>> + * http://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. >>>>>>>> + */ >>>>>>>> + >>>>>>>> +#include <proton/import_export.h> >>>>>>>> + >>>>>>>> +/** @file >>>>>>>> + * URL API for parsing URLs. >>>>>>>> + * >>>>>>>> + * @defgroup url URL >>>>>>>> + * @{ >>>>>>>> + */ >>>>>>>> + >>>>>>>> +/** A parsed URL */ >>>>>>>> +typedef struct pn_url_t pn_url_t; >>>>>>>> + >>>>>>>> +/** Create an empty URL */ >>>>>>>> +PN_EXTERN pn_url_t *pn_url(void); >>>>>>>> + >>>>>>>> +/** Parse a string URL as a pn_url_t. >>>>>>>> + *@param[in] url A URL string. >>>>>>>> + *@return The parsed pn_url_t or NULL if url is not a valid >> URL >>>>>> string. >>>>>>>> + */ >>>>>>>> +PN_EXTERN pn_url_t *pn_url_parse(const char *url); >>>>>>>> + >>>>>>>> +/** Free a URL */ >>>>>>>> +PN_EXTERN void pn_url_free(pn_url_t *url); >>>>>>>> + >>>>>>>> +/** Clear the contents of the URL. */ >>>>>>>> +PN_EXTERN void pn_url_clear(pn_url_t *url); >>>>>>>> + >>>>>>>> +/** Return the string form of a URL. Owned by the pn_url_t.*/ >>>>>>>> +PN_EXTERN const char *pn_url_str(pn_url_t *url); >>>>>>>> + >>>>>>>> +/** >>>>>>>> + *@name Getters for parts of the URL. >>>>>>>> + * >>>>>>>> + *Values belong to the URL. May return NULL if the value is >> not >>>> set. >>>>>>>> + * >>>>>>>> + *@{ >>>>>>>> + */ >>>>>>>> +PN_EXTERN const char *pn_url_scheme(pn_url_t *url); >>>>>>>> +PN_EXTERN const char *pn_url_username(pn_url_t *url); >>>>>>>> +PN_EXTERN const char *pn_url_password(pn_url_t *url); >>>>>>>> +PN_EXTERN const char *pn_url_host(pn_url_t *url); >>>>>>>> +PN_EXTERN const char *pn_url_port(pn_url_t *url); >>>>>>>> +PN_EXTERN const char *pn_url_path(pn_url_t *url); >>>>>>>> +///@} >>>>>>>> + >>>>>>>> +/** >>>>>>>> + *@name Setters for parts of the URL. >>>>>>>> + * >>>>>>>> + *Values are copied. Value can be NULL to indicate the part >> is not >>>>>> set. >>>>>>>> + * >>>>>>>> + *@{ >>>>>>>> + */ >>>>>>>> +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char >>>> *scheme); >>>>>>>> +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char >>>>>> *username); >>>>>>>> +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char >>>>>> *password); >>>>>>>> +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char >> *host); >>>>>>>> +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char >> *port); >>>>>>>> +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char >> *path); >>>>>>>> +///@} >>>>>>>> + >>>>>>>> +///@} >>>>>>>> +#endif >>>>>>>> >>>>>>>> Added: qpid/proton/trunk/proton-c/src/url.c >>>>>>>> URL: >>>>>>>> >>>>>> >>>> >> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto >>>>>>>> >>>>>>>> >>>>>> >>>> >> ============================================================================== >>>>>>>> --- qpid/proton/trunk/proton-c/src/url.c (added) >>>>>>>> +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50 >> 2014 >>>>>>>> @@ -0,0 +1,127 @@ >>>>>>>> +/* >>>>>>>> + * >>>>>>>> + * Licensed to the Apache Software Foundation (ASF) under one >>>>>>>> + * or more contributor license agreements. See the NOTICE >> file >>>>>>>> + * distributed with this work for additional information >>>>>>>> + * regarding copyright ownership. The ASF licenses this file >>>>>>>> + * to you 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 >>>>>>>> + * >>>>>>>> + * http://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. >>>>>>>> + * >>>>>>>> + */ >>>>>>>> + >>>>>>>> +#include <proton/url.h> >>>>>>>> +#include <proton/util.h> >>>>>>>> +#include <stdlib.h> >>>>>>>> +#include <string.h> >>>>>>>> +#include <stdio.h> >>>>>>>> + >>>>>>>> +static char* copy(const char* str) { >>>>>>>> + if (str == NULL) return NULL; >>>>>>>> + char *str2 = (char*)malloc(strlen(str)); >>>>>>>> + if (str2) strcpy(str2, str); >>>>>>>> + return str2; >>>>>>>> +} >>>>>>>> + >>>>>>>> +struct pn_url_t { >>>>>>>> + char *scheme; >>>>>>>> + char *username; >>>>>>>> + char *password; >>>>>>>> + char *host; >>>>>>>> + char *port; >>>>>>>> + char *path; >>>>>>>> + char *str; >>>>>>>> +}; >>>>>>>> + >>>>>>>> +PN_EXTERN pn_url_t *pn_url() { >>>>>>>> + pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t)); >>>>>>>> + memset(url, 0, sizeof(*url)); >>>>>>>> + return url; >>>>>>>> +} >>>>>>>> + >>>>>>>> +/** Parse a string URL as a pn_url_t. >>>>>>>> + *@param[in] url A URL string. >>>>>>>> + *@return The parsed pn_url_t or NULL if url is not a valid >> URL >>>>>> string. >>>>>>>> + */ >>>>>>>> +PN_EXTERN pn_url_t *pn_url_parse(const char *str) { >>>>>>>> + if (!str || !*str) /* Empty string or NULL is >>>> illegal. */ >>>>>>>> + return NULL; >>>>>>>> + >>>>>>>> + pn_url_t *url = pn_url(); >>>>>>>> + char *str2 = copy(str); /* FIXME aconway >> 2014-09-19: >>>>>> clean up >>>>>>>> */ >>>>>>>> + pni_parse_url(str2, &url->scheme, &url->username, >>>> &url->password, >>>>>>>> &url->host, &url->port, &url->path); >>>>>>>> + url->scheme = copy(url->scheme); >>>>>>>> + url->username = copy(url->username); >>>>>>>> + url->password = copy(url->password); >>>>>>>> + url->host = (url->host && !*url->host) ? NULL : >>>> copy(url->host); >>>>>>>> + url->port = copy(url->port); >>>>>>>> + url->path = copy(url->path); >>>>>>>> + return url; >>>>>>>> +} >>>>>>>> + >>>>>>>> +/** Free a URL */ >>>>>>>> +PN_EXTERN void pn_url_free(pn_url_t *url) { >>>>>>>> + pn_url_clear(url); >>>>>>>> + free(url); >>>>>>>> +} >>>>>>>> + >>>>>>>> +/** Clear the contents of the URL. */ >>>>>>>> +PN_EXTERN void pn_url_clear(pn_url_t *url) { >>>>>>>> + pn_url_set_username(url, NULL); >>>>>>>> + pn_url_set_password(url, NULL); >>>>>>>> + pn_url_set_host(url, NULL); >>>>>>>> + pn_url_set_port(url, NULL); >>>>>>>> + pn_url_set_path(url, NULL); >>>>>>>> + free(url->str); url->str = NULL; >>>>>>>> +} >>>>>>>> + >>>>>>>> +static inline int len(const char *str) { return str ? >> strlen(str) >>>> : >>>>>> 0; } >>>>>>>> + >>>>>>>> +/** Return the string form of a URL. */ >>>>>>>> +PN_EXTERN const char *pn_url_str(pn_url_t *url) { >>>>>>>> + int size = len(url->scheme) + len(url->username) + >>>>>> len(url->password) >>>>>>>> + + len(url->host) + len(url->port) + len(url->path) >>>>>>>> + + len("s://u:p@[h]:p/p"); >>>>>>>> + free(url->str); >>>>>>>> + url->str = (char*)malloc(size); >>>>>>>> + if (!url->str) return NULL; >>>>>>>> + >>>>>>>> + int i = 0; >>>>>>>> + if (url->scheme) i += snprintf(url->str+i, size-i, >> "%s://", >>>>>>>> url->scheme); >>>>>>>> + if (url->username) i += snprintf(url->str+i, size-i, "%s", >>>>>>>> url->username); >>>>>>>> + if (url->password) i += snprintf(url->str+i, size-i, >> ":%s", >>>>>>>> url->password); >>>>>>>> + if (url->username || url->password) i += >> snprintf(url->str+i, >>>>>> size-i, >>>>>>>> "@"); >>>>>>>> + if (url->host) { >>>>>>>> + if (strchr(url->host, ':')) i += snprintf(url->str+i, >>>> size-i, >>>>>>>> "[%s]", url->host); >>>>>>>> + else i += snprintf(url->str+i, size-i, "%s", >> url->host); >>>>>>>> + } >>>>>>>> + if (url->port) i += snprintf(url->str+i, size-i, ":%s", >>>>>> url->port); >>>>>>>> + if (url->path) i += snprintf(url->str+i, size-i, "/%s", >>>>>> url->path); >>>>>>>> + return url->str; >>>>>>>> +} >>>>>>>> + >>>>>>>> +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return >>>>>> url->scheme; } >>>>>>>> +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return >>>>>>>> url->username; } >>>>>>>> +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return >>>>>>>> url->password; } >>>>>>>> +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return >>>> url->host; } >>>>>>>> +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return >>>> url->port; } >>>>>>>> +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return >>>> url->path; } >>>>>>>> + >>>>>>>> +#define SET(part) free(url->part); url->part = copy(part) >>>>>>>> +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char >>>> *scheme) { >>>>>>>> SET(scheme); } >>>>>>>> +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char >>>>>> *username) { >>>>>>>> SET(username); } >>>>>>>> +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char >>>>>> *password) { >>>>>>>> SET(password); } >>>>>>>> +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char >> *host) { >>>>>>>> SET(host); } >>>>>>>> +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char >> *port) { >>>>>>>> SET(port); } >>>>>>>> +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char >> *path) { >>>>>>>> SET(path); } >>>>>>>> + >>>>>>>> + >>>>>>>> >>>>>>>> Modified: qpid/proton/trunk/tests/python/proton_tests/url.py >>>>>>>> URL: >>>>>>>> >>>>>> >>>> >> http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff >>>>>>>> >>>>>>>> >>>>>> >>>> >> ============================================================================== >>>>>>>> --- qpid/proton/trunk/tests/python/proton_tests/url.py >> (original) >>>>>>>> +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep >> 19 >>>>>> 21:00:50 >>>>>>>> 2014 >>>>>>>> @@ -28,9 +28,9 @@ class UrlTest(common.Test): >>>>>>>> def assertNotEqual(self, a, b): >>>>>>>> assert a != b, "%s == %s" % (a, b) >>>>>>>> >>>>>>>> - def assertUrl(self, u, scheme, user, password, host, port, >>>> path): >>>>>>>> - self.assertEqual((u.scheme, u.user, u.password, >> u.host, >>>>>> u.port, >>>>>>>> u.path), >>>>>>>> - (scheme, user, password, host, port, >>>> path)) >>>>>>>> + def assertUrl(self, u, scheme, username, password, host, >> port, >>>>>> path): >>>>>>>> + self.assertEqual((u.scheme, u.username, u.password, >>>> u.host, >>>>>>>> u.port, u.path), >>>>>>>> + (scheme, username, password, host, >> port, >>>>>> path)) >>>>>>>> >>>>>>>> def testUrl(self): >>>>>>>> url = Url('amqp://me:secret@myhost:1234/foobar') >>>>>>>> @@ -40,7 +40,7 @@ class UrlTest(common.Test): >>>>>>>> >>>>>>>> def testDefaults(self): >>>>>>>> # Check that we allow None for scheme, port >>>>>>>> - url = Url(user='me', password='secret', host='myhost', >>>>>>>> path='foobar') >>>>>>>> + url = Url(username='me', password='secret', >> host='myhost', >>>>>>>> path='foobar') >>>>>>>> self.assertEqual(str(url), "me:secret@myhost/foobar") >>>>>>>> self.assertUrl(url, None, 'me', 'secret', 'myhost', >> None, >>>>>>>> 'foobar') >>>>>>>> >>>>>>>> @@ -97,21 +97,19 @@ class UrlTest(common.Test): >>>>>>>> def testMissing(self): >>>>>>>> self.assertUrl(Url(), None, None, None, None, None, >> None) >>>>>>>> self.assertUrl(Url('amqp://'), 'amqp', None, None, >> None, >>>> None, >>>>>>>> None) >>>>>>>> - self.assertUrl(Url('user@'), None, 'user', None, >> None, >>>> None, >>>>>>>> None) >>>>>>>> + self.assertUrl(Url('username@'), None, 'username', >> None, >>>>>> None, >>>>>>>> None, None) >>>>>>>> self.assertUrl(Url(':pass@'), None, '', 'pass', None, >>>> None, >>>>>> None) >>>>>>>> self.assertUrl(Url('host'), None, None, None, 'host', >>>> None, >>>>>> None) >>>>>>>> self.assertUrl(Url(':1234'), None, None, None, None, >> 1234, >>>>>> None) >>>>>>>> self.assertUrl(Url('/path'), None, None, None, None, >> None, >>>>>> 'path') >>>>>>>> >>>>>>>> - for s in ['amqp://', 'user@', ':pass@', ':1234', >>>> '/path']: >>>>>>>> + for s in ['amqp://', 'username@', ':pass@', ':1234', >>>>>> '/path']: >>>>>>>> self.assertEqual(s, str(Url(s))) >>>>>>>> >>>>>>>> for s, full in [ >>>>>>>> ('amqp://', 'amqp://0.0.0.0:amqp'), >>>>>>>> - ('user@', 'amqp://user@0.0.0.0:amqp'), >>>>>>>> + ('username@', 'amqp://username@0.0.0.0: >> amqp'), >>>>>>>> (':pass@', 'amqp://:pass@0.0.0.0:amqp'), >>>>>>>> (':1234', 'amqp://0.0.0.0:1234'), >>>>>>>> ('/path', 'amqp://0.0.0.0:amqp/path')]: >>>>>>>> self.assertEqual(str(Url(s).defaults()), full) >>>>>>>> - >>>>>>>> - self.assertRaises(ValueError, Url, '') >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>> --------------------------------------------------------------------- >>>>>>>> To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org >>>>>>>> For additional commands, e-mail: commits-h...@qpid.apache.org >>>>>>>> >>>>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >> --------------------------------------------------------------------- >>>>>> To unsubscribe, e-mail: dev-unsubscr...@qpid.apache.org >>>>>> For additional commands, e-mail: dev-h...@qpid.apache.org >>>>>> >>>>>> >>>> >>>> >>>> >>>> --------------------------------------------------------------------- >>>> To unsubscribe, e-mail: dev-unsubscr...@qpid.apache.org >>>> For additional commands, e-mail: dev-h...@qpid.apache.org >>>> >>>> >> >> >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: dev-unsubscr...@qpid.apache.org >> For additional commands, e-mail: dev-h...@qpid.apache.org >> >>