LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/svl/qa/unit - test_URIHelper.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 75 127 59.1 %
Date: 2013-07-09 Functions: 21 29 72.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <cassert>
      21             : #include <cstddef>
      22             : 
      23             : #include "com/sun/star/lang/Locale.hpp"
      24             : #include "com/sun/star/lang/XComponent.hpp"
      25             : #include "com/sun/star/lang/XMultiServiceFactory.hpp"
      26             : #include "com/sun/star/ucb/Command.hpp"
      27             : #include "com/sun/star/ucb/CommandAbortedException.hpp"
      28             : #include "com/sun/star/ucb/IllegalIdentifierException.hpp"
      29             : #include "com/sun/star/ucb/UniversalContentBroker.hpp"
      30             : #include "com/sun/star/ucb/XCommandProcessor.hpp"
      31             : #include "com/sun/star/ucb/XContent.hpp"
      32             : #include "com/sun/star/ucb/XContentIdentifier.hpp"
      33             : #include "com/sun/star/ucb/XContentProvider.hpp"
      34             : #include "com/sun/star/uno/Any.hxx"
      35             : #include "com/sun/star/uno/Exception.hpp"
      36             : #include "com/sun/star/uno/Reference.hxx"
      37             : #include "com/sun/star/uno/RuntimeException.hpp"
      38             : #include "com/sun/star/uno/XComponentContext.hpp"
      39             : #include "com/sun/star/uri/XUriReference.hpp"
      40             : #include "cppuhelper/bootstrap.hxx"
      41             : #include "cppuhelper/implbase1.hxx"
      42             : #include "cppuhelper/implbase2.hxx"
      43             : #include "cppunit/TestCase.h"
      44             : #include "cppunit/TestFixture.h"
      45             : #include "cppunit/TestSuite.h"
      46             : #include "cppunit/extensions/HelperMacros.h"
      47             : #include "cppunit/plugin/TestPlugIn.h"
      48             : #include "rtl/strbuf.hxx"
      49             : #include "rtl/string.h"
      50             : #include "rtl/string.hxx"
      51             : #include "rtl/textenc.h"
      52             : #include "rtl/ustring.h"
      53             : #include "rtl/ustring.hxx"
      54             : #include "sal/macros.h"
      55             : #include "sal/types.h"
      56             : #include "svl/urihelper.hxx"
      57             : #include "tools/solar.h"
      58             : #include "unotools/charclass.hxx"
      59             : 
      60             : namespace com { namespace sun { namespace star { namespace ucb {
      61             :     class XCommandEnvironment;
      62             :     class XContentEventListener;
      63             : } } } }
      64             : 
      65             : namespace {
      66             : 
      67             : // This class only implements that subset of functionality of a proper
      68             : // css::ucb::Content that is known to be needed here:
      69          32 : class Content:
      70             :     public cppu::WeakImplHelper2<
      71             :         css::ucb::XContent, css::ucb::XCommandProcessor >
      72             : {
      73             : public:
      74             :     explicit Content(
      75             :         css::uno::Reference< css::ucb::XContentIdentifier > const & identifier);
      76             : 
      77             :     virtual css::uno::Reference< css::ucb::XContentIdentifier > SAL_CALL
      78           0 :     getIdentifier() throw (css::uno::RuntimeException) {
      79           0 :         return m_identifier;
      80             :     }
      81             : 
      82           0 :     virtual OUString SAL_CALL getContentType()
      83             :         throw (css::uno::RuntimeException)
      84             :     {
      85           0 :         return OUString();
      86             :     }
      87             : 
      88           0 :     virtual void SAL_CALL addContentEventListener(
      89             :         css::uno::Reference< css::ucb::XContentEventListener > const &)
      90             :         throw (css::uno::RuntimeException)
      91           0 :     {}
      92             : 
      93           0 :     virtual void SAL_CALL removeContentEventListener(
      94             :         css::uno::Reference< css::ucb::XContentEventListener > const &)
      95             :         throw (css::uno::RuntimeException)
      96           0 :     {}
      97             : 
      98           0 :     virtual sal_Int32 SAL_CALL createCommandIdentifier()
      99             :         throw (css::uno::RuntimeException)
     100             :     {
     101           0 :         return 0;
     102             :     }
     103             : 
     104             :     virtual css::uno::Any SAL_CALL execute(
     105             :         css::ucb::Command const & command, sal_Int32 commandId,
     106             :         css::uno::Reference< css::ucb::XCommandEnvironment > const &)
     107             :         throw (
     108             :             css::uno::Exception, css::ucb::CommandAbortedException,
     109             :             css::uno::RuntimeException);
     110             : 
     111           0 :     virtual void SAL_CALL abort(sal_Int32) throw (css::uno::RuntimeException) {}
     112             : 
     113             : private:
     114             :     static char const m_prefix[];
     115             : 
     116             :     css::uno::Reference< css::ucb::XContentIdentifier > m_identifier;
     117             : };
     118             : 
     119             : char const Content::m_prefix[] = "test:";
     120             : 
     121          16 : Content::Content(
     122             :     css::uno::Reference< css::ucb::XContentIdentifier > const & identifier):
     123          16 :     m_identifier(identifier)
     124             : {
     125             :     assert(m_identifier.is());
     126          16 :     OUString uri(m_identifier->getContentIdentifier());
     127          32 :     if (!uri.matchIgnoreAsciiCase(m_prefix)
     128          16 :         || uri.indexOf('#', RTL_CONSTASCII_LENGTH(m_prefix)) != -1)
     129             :     {
     130           0 :         throw css::ucb::IllegalIdentifierException();
     131          16 :     }
     132          16 : }
     133             : 
     134          16 : css::uno::Any Content::execute(
     135             :     css::ucb::Command const & command, sal_Int32,
     136             :     css::uno::Reference< css::ucb::XCommandEnvironment > const &)
     137             :     throw (
     138             :         css::uno::Exception, css::ucb::CommandAbortedException,
     139             :         css::uno::RuntimeException)
     140             : {
     141          16 :     if ( command.Name != "getCasePreservingURL" )
     142             :     {
     143           0 :         throw css::uno::RuntimeException();
     144             :     }
     145             :     // If any non-empty segment starts with anything but '0', '1', or '2', fail;
     146             :     // otherwise, if the last non-empty segment starts with '1', add a final
     147             :     // slash, and if the last non-empty segment starts with '2', remove a final
     148             :     // slash (if any); also, turn the given uri into all-lowercase:
     149          16 :     OUString uri(m_identifier->getContentIdentifier());
     150          16 :     sal_Unicode c = '0';
     151          72 :     for (sal_Int32 i = RTL_CONSTASCII_LENGTH(m_prefix); i != -1;) {
     152          48 :         OUString seg(uri.getToken(0, '/', i));
     153          48 :         if (seg.getLength() > 0) {
     154          30 :             c = seg[0];
     155          30 :             if (c < '0' || c > '2') {
     156           8 :                 throw css::uno::Exception();
     157             :             }
     158             :         }
     159          48 :     }
     160           8 :     switch (c) {
     161             :     case '1':
     162           2 :         uri += "/";
     163           2 :         break;
     164             :     case '2':
     165           2 :         if (uri.getLength() > 0 && uri[uri.getLength() - 1] == '/') {
     166           1 :             uri = uri.copy(0, uri.getLength() -1);
     167             :         }
     168           2 :         break;
     169             :     }
     170           8 :     return css::uno::makeAny(uri.toAsciiLowerCase());
     171             : }
     172             : 
     173           3 : class Provider: public cppu::WeakImplHelper1< css::ucb::XContentProvider > {
     174             : public:
     175          16 :     virtual css::uno::Reference< css::ucb::XContent > SAL_CALL queryContent(
     176             :         css::uno::Reference< css::ucb::XContentIdentifier > const & identifier)
     177             :         throw (css::ucb::IllegalIdentifierException, css::uno::RuntimeException)
     178             :     {
     179          16 :         return new Content(identifier);
     180             :     }
     181             : 
     182           0 :     virtual sal_Int32 SAL_CALL compareContentIds(
     183             :         css::uno::Reference< css::ucb::XContentIdentifier > const & id1,
     184             :         css::uno::Reference< css::ucb::XContentIdentifier > const & id2)
     185             :         throw (css::uno::RuntimeException)
     186             :     {
     187             :         assert(id1.is() && id2.is());
     188             :         return
     189           0 :             id1->getContentIdentifier().compareTo(id2->getContentIdentifier());
     190             :     }
     191             : };
     192             : 
     193           9 : class Test: public CppUnit::TestFixture {
     194             : public:
     195             :     virtual void setUp();
     196             : 
     197             :     void finish();
     198             : 
     199             :     void testNormalizedMakeRelative();
     200             : 
     201             :     void testFindFirstURLInText();
     202             : 
     203           2 :     CPPUNIT_TEST_SUITE(Test);
     204           1 :     CPPUNIT_TEST(testNormalizedMakeRelative);
     205           1 :     CPPUNIT_TEST(testFindFirstURLInText);
     206           1 :     CPPUNIT_TEST(finish);
     207           2 :     CPPUNIT_TEST_SUITE_END();
     208             : 
     209             : private:
     210             :     static css::uno::Reference< css::uno::XComponentContext > m_context;
     211             : };
     212             : 
     213           3 : void Test::setUp() {
     214             :     // For whatever reason, on W32 it does not work to create/destroy a fresh
     215             :     // component context for each test in Test::setUp/tearDown; therefore, a
     216             :     // single component context is used for all tests and destroyed in the last
     217             :     // pseudo-test "finish":
     218           3 :     if (!m_context.is()) {
     219           1 :         m_context = cppu::defaultBootstrap_InitialComponentContext();
     220             :     }
     221           3 : }
     222             : 
     223           1 : void Test::finish() {
     224             :     css::uno::Reference< css::lang::XComponent >(
     225           1 :         m_context, css::uno::UNO_QUERY_THROW)->dispose();
     226           1 : }
     227             : 
     228           1 : void Test::testNormalizedMakeRelative() {
     229           2 :     css::ucb::UniversalContentBroker::create(m_context)->
     230             :         registerContentProvider(
     231           1 :             new Provider, OUString("test"),
     232           2 :             true);
     233             :     struct Data {
     234             :         char const * base;
     235             :         char const * absolute;
     236             :         char const * relative;
     237             :     };
     238             :     static Data const tests[] = {
     239             :         { "hierarchical:/", "mailto:def@a.b.c.", "mailto:def@a.b.c." },
     240             :         { "hierarchical:/", "a/b/c", "a/b/c" },
     241             :         { "hierarchical:/a", "hierarchical:/a/b/c?d#e", "/a/b/c?d#e" },
     242             :         { "hierarchical:/a/", "hierarchical:/a/b/c?d#e", "b/c?d#e" },
     243             :         { "test:/0/0/a", "test:/0/b", "../b" },
     244             :         { "test:/1/1/a", "test:/1/b", "../b" },
     245             :         { "test:/2/2//a", "test:/2/b", "../../b" },
     246             :         { "test:/0a/b", "test:/0A/c#f", "c#f" },
     247             :         { "file:///usr/bin/nonex1/nonex2",
     248             :           "file:///usr/bin/nonex1/nonex3/nonex4", "nonex3/nonex4" },
     249             :         { "file:///usr/bin/nonex1/nonex2#fragmentA",
     250             :           "file:///usr/bin/nonex1/nonex3/nonex4#fragmentB",
     251             :           "nonex3/nonex4#fragmentB" },
     252             :         { "file:///usr/nonex1/nonex2", "file:///usr/nonex3", "../nonex3" },
     253             :         { "file:///c:/windows/nonex1", "file:///c:/nonex2", "../nonex2" },
     254             : #if defined WNT
     255             :         { "file:///c:/nonex1/nonex2", "file:///C:/nonex1/nonex3/nonex4",
     256             :           "nonex3/nonex4" }
     257             : #endif
     258             :     };
     259          13 :     for (std::size_t i = 0; i < SAL_N_ELEMENTS(tests); ++i) {
     260             :         css::uno::Reference< css::uri::XUriReference > ref(
     261             :             URIHelper::normalizedMakeRelative(
     262             :                 m_context, OUString::createFromAscii(tests[i].base),
     263          12 :                 OUString::createFromAscii(tests[i].absolute)));
     264          12 :         bool ok = tests[i].relative == 0
     265           0 :             ? !ref.is()
     266          12 :             : ref.is() && ref->getUriReference().equalsAscii(tests[i].relative);
     267          24 :         OString msg;
     268          12 :         if (!ok) {
     269           0 :             OStringBuffer buf;
     270           0 :             buf.append('<');
     271           0 :             buf.append(tests[i].base);
     272           0 :             buf.append(">, <");
     273           0 :             buf.append(tests[i].absolute);
     274           0 :             buf.append(">: ");
     275           0 :             if (ref.is()) {
     276           0 :                 buf.append('<');
     277             :                 buf.append(
     278             :                     OUStringToOString(
     279           0 :                         ref->getUriReference(), RTL_TEXTENCODING_UTF8));
     280           0 :                 buf.append('>');
     281             :             } else {
     282           0 :                 buf.append("none");
     283             :             }
     284           0 :             buf.append(" instead of ");
     285           0 :             if (tests[i].relative == 0) {
     286           0 :                 buf.append("none");
     287             :             } else {
     288           0 :                 buf.append('<');
     289           0 :                 buf.append(tests[i].relative);
     290           0 :                 buf.append('>');
     291             :             }
     292           0 :             msg = buf.makeStringAndClear();
     293             :         }
     294          12 :         CPPUNIT_ASSERT_MESSAGE(msg.getStr(), ok);
     295          12 :     }
     296           1 : }
     297             : 
     298           1 : void Test::testFindFirstURLInText() {
     299             :     struct Data {
     300             :         char const * input;
     301             :         char const * result;
     302             :         sal_Int32 begin;
     303             :         sal_Int32 end;
     304             :     };
     305             :     static Data const tests[] = {
     306             :         { "...ftp://bla.bla.bla/blubber/...",
     307             :           "ftp://bla.bla.bla/blubber/", 3, 29 },
     308             :         { "..\\ftp://bla.bla.bla/blubber/...", 0, 0, 0 },
     309             :         { "..\\ftp:\\\\bla.bla.bla\\blubber/...",
     310             : //Sync with tools/source/fsys/urlobj.cxx and changeScheme
     311             : #ifdef LINUX
     312             :           "smb://bla.bla.bla/blubber%2F", 7, 29 },
     313             : #else
     314             :           "file://bla.bla.bla/blubber%2F", 7, 29 },
     315             : #endif
     316             :         { "http://sun.com", "http://sun.com/", 0, 14 },
     317             :         { "http://sun.com/", "http://sun.com/", 0, 15 },
     318             :         { "http://www.xerox.com@www.pcworld.com/go/3990332.htm", 0, 0, 0 },
     319             :         { "ftp://www.xerox.com@www.pcworld.com/go/3990332.htm",
     320             :           "ftp://www.xerox.com@www.pcworld.com/go/3990332.htm", 0, 50 },
     321             :         { "Version.1.2.3", 0, 0, 0 },
     322             :         { "Version:1.2.3", 0, 0, 0 },
     323             :         { "a.b.c", 0, 0, 0 },
     324             :         { "file:///a|...", "file:///a:", 0, 10 },
     325             :         { "file:///a||...", "file:///a%7C%7C", 0, 11 },
     326             :         { "file:///a|/bc#...", "file:///a:/bc", 0, 13 },
     327             :         { "file:///a|/bc#de...", "file:///a:/bc#de", 0, 16 },
     328             :         { "abc.def.ghi,ftp.xxx.yyy/zzz...", "ftp://ftp.xxx.yyy/zzz", 12, 27 },
     329             :         { "abc.def.ghi,Ftp.xxx.yyy/zzz...", "ftp://Ftp.xxx.yyy/zzz", 12, 27 },
     330             :         { "abc.def.ghi,www.xxx.yyy...", "http://www.xxx.yyy/", 12, 23 },
     331             :         { "abc.def.ghi,wwww.xxx.yyy...", 0, 0, 0 },
     332             :         { "abc.def.ghi,wWW.xxx.yyy...", "http://wWW.xxx.yyy/", 12, 23 },
     333             :         { "Bla {mailto.me@abc.def.g.h.i}...",
     334             :           "mailto:%7Bmailto.me@abc.def.g.h.i", 4, 28 },
     335             :         { "abc@def@ghi", 0, 0, 0 },
     336             :         { "lala@sun.com", "mailto:lala@sun.com", 0, 12 },
     337             :         { "1lala@sun.com", "mailto:1lala@sun.com", 0, 13 },
     338             :         { "aaa_bbb@xxx.yy", "mailto:aaa_bbb@xxx.yy", 0, 14 },
     339             :         { "{a:\\bla/bla/bla...}", "file:///a:/bla/bla/bla", 1, 15 },
     340             :         { "#b:/c/d#e#f#", "file:///b:/c/d", 1, 7 },
     341             :         { "a:/", "file:///a:/", 0, 3 },
     342             :         { ".component:", 0, 0, 0 },
     343             :         { ".uno:", 0, 0, 0 },
     344             :         { "cid:", 0, 0, 0 },
     345             :         { "data:", 0, 0, 0 },
     346             :         { "db:", 0, 0, 0 },
     347             :         { "file:", 0, 0, 0 },
     348             :         { "ftp:", 0, 0, 0 },
     349             :         { "http:", 0, 0, 0 },
     350             :         { "https:", 0, 0, 0 },
     351             :         { "imap:", 0, 0, 0 },
     352             :         { "javascript:", 0, 0, 0 },
     353             :         { "ldap:", 0, 0, 0 },
     354             :         { "macro:", 0, 0, 0 },
     355             :         { "mailto:", 0, 0, 0 },
     356             :         { "news:", 0, 0, 0 },
     357             :         { "out:", 0, 0, 0 },
     358             :         { "pop3:", 0, 0, 0 },
     359             :         { "private:", 0, 0, 0 },
     360             :         { "slot:", 0, 0, 0 },
     361             :         { "staroffice.component:", 0, 0, 0 },
     362             :         { "staroffice.db:", 0, 0, 0 },
     363             :         { "staroffice.factory:", 0, 0, 0 },
     364             :         { "staroffice.helpid:", 0, 0, 0 },
     365             :         { "staroffice.java:", 0, 0, 0 },
     366             :         { "staroffice.macro:", 0, 0, 0 },
     367             :         { "staroffice.out:", 0, 0, 0 },
     368             :         { "staroffice.pop3:", 0, 0, 0 },
     369             :         { "staroffice.private:", 0, 0, 0 },
     370             :         { "staroffice.searchfolder:", 0, 0, 0 },
     371             :         { "staroffice.slot:", 0, 0, 0 },
     372             :         { "staroffice.trashcan:", 0, 0, 0 },
     373             :         { "staroffice.uno:", 0, 0, 0 },
     374             :         { "staroffice.vim:", 0, 0, 0 },
     375             :         { "staroffice:", 0, 0, 0 },
     376             :         { "vim:", 0, 0, 0 },
     377             :         { "vnd.sun.star.cmd:", 0, 0, 0 },
     378             :         { "vnd.sun.star.help:", 0, 0, 0 },
     379             :         { "vnd.sun.star.hier:", 0, 0, 0 },
     380             :         { "vnd.sun.star.pkg:", 0, 0, 0 },
     381             :         { "vnd.sun.star.script:", 0, 0, 0 },
     382             :         { "vnd.sun.star.webdav:", 0, 0, 0 },
     383             :         { "vnd.sun.star.wfs:", 0, 0, 0 },
     384             :         { "generic:path", 0, 0, 0 },
     385             :         { "wfs:", 0, 0, 0 }
     386             :     };
     387           1 :     CharClass charClass( m_context, LanguageTag( com::sun::star::lang::Locale("en", "US", "")));
     388          72 :     for (std::size_t i = 0; i < SAL_N_ELEMENTS(tests); ++i) {
     389          71 :         OUString input(OUString::createFromAscii(tests[i].input));
     390          71 :         sal_Int32 begin = 0;
     391          71 :         sal_Int32 end = input.getLength();
     392             :         OUString result(
     393         142 :             URIHelper::FindFirstURLInText(input, begin, end, charClass));
     394          71 :         bool ok = tests[i].result == 0
     395         102 :             ? (result.getLength() == 0 && begin == input.getLength()
     396         102 :                && end == input.getLength())
     397          40 :             : (result.equalsAscii(tests[i].result) && begin == tests[i].begin
     398         162 :                && end == tests[i].end);
     399         142 :         OString msg;
     400          71 :         if (!ok) {
     401           0 :             OStringBuffer buf;
     402           0 :             buf.append('"');
     403           0 :             buf.append(tests[i].input);
     404           0 :             buf.append("\" -> ");
     405           0 :             buf.append(tests[i].result == 0 ? "none" : tests[i].result);
     406           0 :             buf.append(" (");
     407           0 :             buf.append(static_cast< sal_Int32 >(tests[i].begin));
     408           0 :             buf.append(", ");
     409           0 :             buf.append(static_cast< sal_Int32 >(tests[i].end));
     410           0 :             buf.append(')');
     411           0 :             buf.append(" != ");
     412           0 :             buf.append(OUStringToOString(result, RTL_TEXTENCODING_UTF8));
     413           0 :             buf.append(" (");
     414           0 :             buf.append(static_cast< sal_Int32 >(begin));
     415           0 :             buf.append(", ");
     416           0 :             buf.append(static_cast< sal_Int32 >(end));
     417           0 :             buf.append(')');
     418           0 :             msg = buf.makeStringAndClear();
     419             :         }
     420          71 :         CPPUNIT_ASSERT_MESSAGE(msg.getStr(), ok);
     421          72 :     }
     422           1 : }
     423             : 
     424           1 : css::uno::Reference< css::uno::XComponentContext > Test::m_context;
     425             : 
     426           1 : CPPUNIT_TEST_SUITE_REGISTRATION(Test);
     427             : 
     428             : }
     429             : 
     430           4 : CPPUNIT_PLUGIN_IMPLEMENT();
     431             : 
     432             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10