LCOV - code coverage report
Current view: directory - toolkit/components/places/tests/cpp - places_test_harness.h (source / functions) Found Hit Coverage
Test: app.info Lines: 104 102 98.1 %
Date: 2012-06-02 Functions: 20 20 100.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2                 :  * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
       3                 :  * ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is places test code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * the Mozilla Foundation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 2009
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "TestHarness.h"
      41                 : #include "nsMemory.h"
      42                 : #include "nsThreadUtils.h"
      43                 : #include "nsNetUtil.h"
      44                 : #include "nsDocShellCID.h"
      45                 : 
      46                 : #include "nsToolkitCompsCID.h"
      47                 : #include "nsINavHistoryService.h"
      48                 : #include "nsIObserverService.h"
      49                 : #include "mozilla/IHistory.h"
      50                 : #include "mozIStorageConnection.h"
      51                 : #include "mozIStorageStatement.h"
      52                 : #include "nsPIPlacesDatabase.h"
      53                 : #include "nsIObserver.h"
      54                 : #include "prinrval.h"
      55                 : 
      56                 : #define TOPIC_FRECENCY_UPDATED "places-frecency-updated"
      57                 : #define WAITFORTOPIC_TIMEOUT_SECONDS 5
      58                 : 
      59                 : using namespace mozilla;
      60                 : 
      61                 : static size_t gTotalTests = 0;
      62                 : static size_t gPassedTests = 0;
      63                 : 
      64                 : #define do_check_true(aCondition) \
      65                 :   PR_BEGIN_MACRO \
      66                 :     gTotalTests++; \
      67                 :     if (aCondition) { \
      68                 :       gPassedTests++; \
      69                 :     } else { \
      70                 :       fail("%s | Expected true, got false at line %d", __FILE__, __LINE__); \
      71                 :     } \
      72                 :   PR_END_MACRO
      73                 : 
      74                 : #define do_check_false(aCondition) \
      75                 :   PR_BEGIN_MACRO \
      76                 :     gTotalTests++; \
      77                 :     if (!aCondition) { \
      78                 :       gPassedTests++; \
      79                 :     } else { \
      80                 :       fail("%s | Expected false, got true at line %d", __FILE__, __LINE__); \
      81                 :     } \
      82                 :   PR_END_MACRO
      83                 : 
      84                 : #define do_check_success(aResult) \
      85                 :   do_check_true(NS_SUCCEEDED(aResult))
      86                 : 
      87                 : #ifdef LINUX
      88                 : // XXX Linux opt builds on tinderbox are orange due to linking with stdlib.
      89                 : // This is sad and annoying, but it's a workaround that works.
      90                 : #define do_check_eq(aExpected, aActual) \
      91                 :   do_check_true(aExpected == aActual)
      92                 : #else
      93                 : #include <sstream>
      94                 : 
      95                 : #define do_check_eq(aActual, aExpected) \
      96                 :   PR_BEGIN_MACRO \
      97                 :     gTotalTests++; \
      98                 :     if (aExpected == aActual) { \
      99                 :       gPassedTests++; \
     100                 :     } else { \
     101                 :       std::ostringstream temp; \
     102                 :       temp << __FILE__ << " | Expected '" << aExpected << "', got '"; \
     103                 :       temp << aActual <<"' at line " << __LINE__; \
     104                 :       fail(temp.str().c_str()); \
     105                 :     } \
     106                 :   PR_END_MACRO
     107                 : #endif
     108                 : 
     109                 : struct Test
     110                 : {
     111                 :   void (*func)(void);
     112                 :   const char* const name;
     113                 : };
     114                 : #define TEST(aName) \
     115                 :   {aName, #aName}
     116                 : 
     117                 : /**
     118                 :  * Runs the next text.
     119                 :  */
     120                 : void run_next_test();
     121                 : 
     122                 : /**
     123                 :  * To be used around asynchronous work.
     124                 :  */
     125                 : void do_test_pending();
     126                 : void do_test_finished();
     127                 : 
     128                 : /**
     129                 :  * Spins current thread until a topic is received.
     130                 :  */
     131                 : class WaitForTopicSpinner : public nsIObserver
     132                 : {
     133                 : public:
     134                 :   NS_DECL_ISUPPORTS
     135                 : 
     136               7 :   WaitForTopicSpinner(const char* const aTopic)
     137                 :   : mTopicReceived(false)
     138               7 :   , mStartTime(PR_IntervalNow())
     139                 :   {
     140                 :     nsCOMPtr<nsIObserverService> observerService =
     141              14 :       do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
     142               7 :     do_check_true(observerService);
     143               7 :     (void)observerService->AddObserver(this, aTopic, false);
     144               7 :   }
     145                 : 
     146               7 :   void Spin() {
     147              28 :     while (!mTopicReceived) {
     148              14 :       if ((PR_IntervalNow() - mStartTime) > (WAITFORTOPIC_TIMEOUT_SECONDS * PR_USEC_PER_SEC)) {
     149                 :         // Timed out waiting for the topic.
     150               0 :         do_check_true(false);
     151               0 :         break;
     152                 :       }
     153              14 :       (void)NS_ProcessNextEvent();
     154                 :     }
     155               7 :   }
     156                 : 
     157               7 :   NS_IMETHOD Observe(nsISupports* aSubject,
     158                 :                      const char* aTopic,
     159                 :                      const PRUnichar* aData)
     160                 :   {
     161               7 :     mTopicReceived = true;
     162                 :     nsCOMPtr<nsIObserverService> observerService =
     163              14 :       do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
     164               7 :     do_check_true(observerService);
     165               7 :     (void)observerService->RemoveObserver(this, aTopic);
     166               7 :     return NS_OK;
     167                 :   }
     168                 : 
     169                 : private:
     170                 :   bool mTopicReceived;
     171                 :   PRIntervalTime mStartTime;
     172                 : };
     173              98 : NS_IMPL_ISUPPORTS1(
     174                 :   WaitForTopicSpinner,
     175                 :   nsIObserver
     176                 : )
     177                 : 
     178                 : /**
     179                 :  * Adds a URI to the database.
     180                 :  *
     181                 :  * @param aURI
     182                 :  *        The URI to add to the database.
     183                 :  */
     184                 : void
     185               6 : addURI(nsIURI* aURI)
     186                 : {
     187                 :   nsRefPtr<WaitForTopicSpinner> spinner =
     188              12 :     new WaitForTopicSpinner(TOPIC_FRECENCY_UPDATED);
     189                 : 
     190                 :   nsCOMPtr<nsINavHistoryService> hist =
     191              12 :     do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID);
     192                 :   PRInt64 id;
     193               6 :   nsresult rv = hist->AddVisit(aURI, PR_Now(), nsnull,
     194                 :                                nsINavHistoryService::TRANSITION_LINK, false,
     195               6 :                                0, &id);
     196               6 :   do_check_success(rv);
     197                 : 
     198                 :   // Wait for frecency update.
     199               6 :   spinner->Spin();
     200               6 : }
     201                 : 
     202                 : struct PlaceRecord
     203              14 : {
     204                 :   PRInt64 id;
     205                 :   PRInt32 hidden;
     206                 :   PRInt32 typed;
     207                 :   PRInt32 visitCount;
     208                 :   nsCString guid;
     209                 : };
     210                 : 
     211                 : struct VisitRecord
     212                 : {
     213                 :   PRInt64 id;
     214                 :   PRInt64 lastVisitId;
     215                 :   PRInt32 transitionType;
     216                 : };
     217                 : 
     218                 : already_AddRefed<IHistory>
     219              16 : do_get_IHistory()
     220                 : {
     221              32 :   nsCOMPtr<IHistory> history = do_GetService(NS_IHISTORY_CONTRACTID);
     222              16 :   do_check_true(history);
     223              16 :   return history.forget();
     224                 : }
     225                 : 
     226                 : already_AddRefed<nsINavHistoryService>
     227              12 : do_get_NavHistory()
     228                 : {
     229                 :   nsCOMPtr<nsINavHistoryService> serv =
     230              24 :     do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID);
     231              12 :   do_check_true(serv);
     232              12 :   return serv.forget();
     233                 : }
     234                 : 
     235                 : already_AddRefed<mozIStorageConnection>
     236              10 : do_get_db()
     237                 : {
     238              20 :   nsCOMPtr<nsINavHistoryService> history = do_get_NavHistory();
     239              20 :   nsCOMPtr<nsPIPlacesDatabase> database = do_QueryInterface(history);
     240              10 :   do_check_true(database);
     241                 : 
     242                 :   mozIStorageConnection* dbConn;
     243              10 :   nsresult rv = database->GetDBConnection(&dbConn);
     244              10 :   do_check_success(rv);
     245              10 :   return dbConn;
     246                 : }
     247                 : 
     248                 : /**
     249                 :  * Get the place record from the database.
     250                 :  *
     251                 :  * @param aURI The unique URI of the place we are looking up
     252                 :  * @param result Out parameter where the result is stored
     253                 :  */
     254                 : void
     255               7 : do_get_place(nsIURI* aURI, PlaceRecord& result)
     256                 : {
     257              14 :   nsCOMPtr<mozIStorageConnection> dbConn = do_get_db();
     258              14 :   nsCOMPtr<mozIStorageStatement> stmt;
     259                 : 
     260              14 :   nsCString spec;
     261               7 :   nsresult rv = aURI->GetSpec(spec);
     262               7 :   do_check_success(rv);
     263                 : 
     264              14 :   rv = dbConn->CreateStatement(NS_LITERAL_CSTRING(
     265                 :     "SELECT id, hidden, typed, visit_count, guid FROM moz_places "
     266                 :     "WHERE url=?1 "
     267              14 :   ), getter_AddRefs(stmt));
     268               7 :   do_check_success(rv);
     269                 : 
     270               7 :   rv = stmt->BindUTF8StringByIndex(0, spec);
     271               7 :   do_check_success(rv);
     272                 : 
     273                 :   bool hasResults;
     274               7 :   rv = stmt->ExecuteStep(&hasResults);
     275               7 :   do_check_success(rv);
     276               7 :   if (!hasResults) {
     277               1 :     result.id = 0;
     278                 :     return;
     279                 :   }
     280                 : 
     281               6 :   rv = stmt->GetInt64(0, &result.id);
     282               6 :   do_check_success(rv);
     283               6 :   rv = stmt->GetInt32(1, &result.hidden);
     284               6 :   do_check_success(rv);
     285               6 :   rv = stmt->GetInt32(2, &result.typed);
     286               6 :   do_check_success(rv);
     287               6 :   rv = stmt->GetInt32(3, &result.visitCount);
     288               6 :   do_check_success(rv);
     289               6 :   rv = stmt->GetUTF8String(4, result.guid);
     290               6 :   do_check_success(rv);
     291                 : }
     292                 : 
     293                 : /**
     294                 :  * Gets the most recent visit to a place.
     295                 :  *
     296                 :  * @param placeID ID from the moz_places table
     297                 :  * @param result Out parameter where visit is stored
     298                 :  */
     299                 : void
     300               3 : do_get_lastVisit(PRInt64 placeId, VisitRecord& result)
     301                 : {
     302               6 :   nsCOMPtr<mozIStorageConnection> dbConn = do_get_db();
     303               6 :   nsCOMPtr<mozIStorageStatement> stmt;
     304                 : 
     305               6 :   nsresult rv = dbConn->CreateStatement(NS_LITERAL_CSTRING(
     306                 :     "SELECT id, from_visit, visit_type FROM moz_historyvisits "
     307                 :     "WHERE place_id=?1 "
     308                 :     "LIMIT 1"
     309               6 :   ), getter_AddRefs(stmt));
     310               3 :   do_check_success(rv);
     311                 : 
     312               3 :   rv = stmt->BindInt64ByIndex(0, placeId);
     313               3 :   do_check_success(rv);
     314                 : 
     315                 :   bool hasResults;
     316               3 :   rv = stmt->ExecuteStep(&hasResults);
     317               3 :   do_check_success(rv);
     318                 : 
     319               3 :   if (!hasResults) {
     320               1 :     result.id = 0;
     321                 :     return;
     322                 :   }
     323                 : 
     324               2 :   rv = stmt->GetInt64(0, &result.id);
     325               2 :   do_check_success(rv);
     326               2 :   rv = stmt->GetInt64(1, &result.lastVisitId);
     327               2 :   do_check_success(rv);
     328               2 :   rv = stmt->GetInt32(2, &result.transitionType);
     329               2 :   do_check_success(rv);
     330                 : }
     331                 : 
     332                 : static const char TOPIC_PROFILE_CHANGE[] = "profile-before-change";
     333                 : static const char TOPIC_PLACES_CONNECTION_CLOSED[] = "places-connection-closed";
     334                 : 
     335                 : class WaitForConnectionClosed : public nsIObserver
     336               1 : {
     337                 :   nsRefPtr<WaitForTopicSpinner> mSpinner;
     338                 : public:
     339                 :   NS_DECL_ISUPPORTS
     340                 : 
     341               1 :   WaitForConnectionClosed()
     342               1 :   {
     343                 :     nsCOMPtr<nsIObserverService> os =
     344               2 :       do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
     345               1 :     MOZ_ASSERT(os);
     346               1 :     if (os) {
     347               1 :       MOZ_ALWAYS_TRUE(NS_SUCCEEDED(os->AddObserver(this, TOPIC_PROFILE_CHANGE, false)));
     348                 :     }
     349               1 :     mSpinner = new WaitForTopicSpinner(TOPIC_PLACES_CONNECTION_CLOSED);
     350               1 :   }
     351                 : 
     352               1 :   NS_IMETHOD Observe(nsISupports* aSubject,
     353                 :                      const char* aTopic,
     354                 :                      const PRUnichar* aData)
     355                 :   {
     356                 :     nsCOMPtr<nsIObserverService> os =
     357               2 :       do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
     358               1 :     MOZ_ASSERT(os);
     359               1 :     if (os) {
     360               1 :       MOZ_ALWAYS_TRUE(NS_SUCCEEDED(os->RemoveObserver(this, aTopic)));
     361                 :     }
     362                 : 
     363               1 :     mSpinner->Spin();
     364                 : 
     365               1 :     return NS_OK;
     366                 :   }
     367                 : };
     368                 : 
     369              14 : NS_IMPL_ISUPPORTS1(WaitForConnectionClosed, nsIObserver)

Generated by: LCOV version 1.7