diff options
Diffstat (limited to 'tests')
163 files changed, 8448 insertions, 512 deletions
diff --git a/tests/auto/android/AndroidManifest.xml b/tests/auto/android/AndroidManifest.xml new file mode 100644 index 0000000000..32e2b88d66 --- /dev/null +++ b/tests/auto/android/AndroidManifest.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.qtproject.qt5.android.tests" + android:versionCode="1" + android:versionName="1.0"> + <uses-sdk android:minSdkVersion="4" /> + <application android:icon="@drawable/icon" android:label="@string/app_name" android:name="org.qtproject.qt5.android.QtNative"> + <activity android:label="@string/app_name" android:name="org.qtproject.qt5.android.QtActivity"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/> + <uses-permission android:name="android.permission.INTERNET"/> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> + <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> + <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER"/> + <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> + <uses-permission android:name="android.permission.BLUETOOTH"/> + <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> + <uses-permission android:name="android.permission.CAMERA"/> + <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/> + <uses-permission android:name="android.permission.INJECT_EVENTS"/> + <uses-permission android:name="android.permission.NFC"/> + <uses-permission android:name="android.permission.READ_PHONE_STATE"/> + <uses-permission android:name="android.permission.SET_ORIENTATION"/> + <uses-permission android:name="android.permission.STATUS_BAR"/> + <uses-permission android:name="android.permission.VIBRATE"/> + <uses-permission android:name="android.permission.WAKE_LOCK"/> + <uses-permission android:name="android.permission.WRITE_CALENDAR"/> + <uses-permission android:name="android.permission.WRITE_CONTACTS"/> +</manifest> diff --git a/tests/auto/android/res/layout/main.xml b/tests/auto/android/res/layout/main.xml new file mode 100644 index 0000000000..7fe6bbac67 --- /dev/null +++ b/tests/auto/android/res/layout/main.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + > +<TextView + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:id="@+id/textView" + /> +</LinearLayout> diff --git a/tests/auto/android/res/values/libs.xml b/tests/auto/android/res/values/libs.xml new file mode 100644 index 0000000000..7f2858e554 --- /dev/null +++ b/tests/auto/android/res/values/libs.xml @@ -0,0 +1,19 @@ +<?xml version='1.0' encoding='utf-8'?> +<resources> + <array name="qt_libs"> + <item>QtCore</item> + <item>QtGui</item> + <item>QtTest</item> + <item>QtOpenGL</item> + <item>QtNetwork</item> + <item>QtScript</item> + <item>QtSql</item> + <item>QtXml</item> + <item>QtScriptTools</item> + <item>QtSvg</item> + <item>QtXmlPatterns</item> + <item>QtDeclarative</item> + <item>QtWebKit</item> + </array> + <array name="bundled_libs"/> +</resources> diff --git a/tests/auto/android/res/values/strings.xml b/tests/auto/android/res/values/strings.xml new file mode 100644 index 0000000000..faf61040b5 --- /dev/null +++ b/tests/auto/android/res/values/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_name">Quadruplor</string> +</resources> diff --git a/tests/auto/android/runtests.pl b/tests/auto/android/runtests.pl new file mode 100755 index 0000000000..70a242f29f --- /dev/null +++ b/tests/auto/android/runtests.pl @@ -0,0 +1,358 @@ +#!/usr/bin/perl -w +############################################################################# +## +## Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +## Copyright (C) 2012 BogDan Vatra <bogdan@kde.org> +## Contact: http://www.qt-project.org/legal +## +## This file is part of the test suite of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:LGPL$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and Digia. For licensing terms and +## conditions see http://qt.digia.com/licensing. For further information +## use the contact form at http://qt.digia.com/contact-us. +## +## GNU Lesser General Public License Usage +## Alternatively, this file may be used under the terms of the GNU Lesser +## General Public License version 2.1 as published by the Free Software +## Foundation and appearing in the file LICENSE.LGPL included in the +## packaging of this file. Please review the following information to +## ensure the GNU Lesser General Public License version 2.1 requirements +## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +## +## In addition, as a special exception, Digia gives you certain additional +## rights. These rights are described in the Digia Qt LGPL Exception +## version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3.0 as published by the Free Software +## Foundation and appearing in the file LICENSE.GPL included in the +## packaging of this file. Please review the following information to +## ensure the GNU General Public License version 3.0 requirements will be +## met: http://www.gnu.org/copyleft/gpl.html. +## +## +## $QT_END_LICENSE$ +## +############################################################################# + +use Cwd; +use Cwd 'abs_path'; +use File::Basename; +use File::Temp 'tempdir'; +use File::Path 'remove_tree'; +use Getopt::Long; +use Pod::Usage; + +### default options +my @stack = cwd; +my $device_serial=""; # "-s device_serial"; +my $packageName="org.qtproject.qt5.android.tests"; +my $intentName="$packageName/org.qtproject.qt5.android.QtActivity"; +my $jobs = 4; +my $testsubset = ""; +my $man = 0; +my $help = 0; +my $make_clean = 0; +my $deploy_qt = 0; +my $time_out=400; +my $android_sdk_dir = "$ENV{'HOME'}/NecessitasQtSDK/android-sdk"; +my $ant_tool = `which ant`; +chomp $ant_tool; +my $strip_tool=""; +my $readelf_tool=""; +GetOptions('h|help' => \$help + , man => \$man + , 's|serial=s' => \$device_serial + , 't|test=s' => \$testsubset + , 'c|clean' => \$make_clean + , 'd|deploy' => \$deploy_qt + , 'j|jobs=i' => \$jobs + , 'sdk=s' => \$android_sdk_dir + , 'ant=s' => \$ant_tool + , 'strip=s' => \$strip_tool + , 'readelf=s' => \$readelf_tool + ) or pod2usage(2); +pod2usage(1) if $help; +pod2usage(-verbose => 2) if $man; + +my $adb_tool="$android_sdk_dir/platform-tools/adb"; +system("$adb_tool devices") == 0 or die "No device found, please plug/start at least one device/emulator\n"; # make sure we have at least on device attached + +$device_serial = "-s $device_serial" if ($device_serial); +$testsubset="/$testsubset" if ($testsubset); + +$strip_tool="$ENV{'HOME'}/NecessitasQtSDK/android-ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-strip" unless($strip_tool); +$readelf_tool="$ENV{'HOME'}/NecessitasQtSDK/android-ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-readelf" unless($readelf_tool); +$readelf_tool="$readelf_tool -d -w "; + +sub dir +{ +# print "@stack\n"; +} + +sub pushd ($) +{ + unless ( chdir $_[0] ) + { + warn "Error: $!\n"; + return; + } + unshift @stack, cwd; + dir; +} + +sub popd () +{ + @stack > 1 and shift @stack; + chdir $stack[0]; + dir; +} + + +sub waitForProcess +{ + my $process=shift; + my $action=shift; + my $timeout=shift; + my $sleepPeriod=shift; + $sleepPeriod=1 if !defined($sleepPeriod); + print "Waiting for $process ".$timeout*$sleepPeriod." seconds to"; + print $action?" start...\n":" die...\n"; + while ($timeout--) + { + my $output = `$adb_tool $device_serial shell ps 2>&1`; # get current processes + #FIXME check why $output is not matching m/.*S $process\n/ or m/.*S $process$/ (eol) + my $res=($output =~ m/.*S $process/)?1:0; # check the procress + if ($action == $res) + { + print "... succeed\n"; + return 1; + } + sleep($sleepPeriod); + print "timeount in ".$timeout*$sleepPeriod." seconds\n" + } + print "... failed\n"; + return 0; +} + +my $src_dir_qt=abs_path(dirname($0)."/.."); +my $quadruplor_dir="$src_dir_qt/tests/auto/android"; +my $qmake_path="$src_dir_qt/bin/qmake"; +my $tests_dir="$src_dir_qt/tests$testsubset"; +my $temp_dir=tempdir(CLEANUP => 1); +my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); +my $output_dir=$stack[0]."/".(1900+$year)."-$mon-$mday-$hour:$min"; +mkdir($output_dir); +my $sdk_api=0; +my $output = `$adb_tool $device_serial shell getprop`; # get device properties +if ($output =~ m/.*\[ro.build.version.sdk\]: \[(\d+)\]/) +{ + $sdk_api=int($1); + $sdk_api=5 if ($sdk_api>5 && $sdk_api<8); + $sdk_api=9 if ($sdk_api>9); +} + +sub reinstallQuadruplor +{ + pushd($quadruplor_dir); + system("$android_sdk_dir/tools/android update project -p . -t android-4")==0 or die "Can't update project ...\n"; + system("$ant_tool uninstall clean debug install")==0 or die "Can't install Quadruplor\n"; + system("$adb_tool $device_serial shell am start -n $intentName"); # create application folders + waitForProcess($packageName,1,10); + waitForProcess($packageName,0,20); + popd(); +} +sub killProcess +{ + reinstallQuadruplor; +# #### it seems I'm too idiot to use perl regexp +# my $process=shift; +# my $output = `$adb_tool $device_serial shell ps 2>&1`; # get current processes +# $output =~ s/\r//g; # replace all "\r" with "" +# chomp($output); +# print $output; +# if ($output =~ m/^.*_\d+\s+(\d+).*S $process/) # check the procress +# { +# print("Killing $process PID:$1\n"); +# system("$adb_tool $device_serial shell kill $1"); +# waitForProcess($process,0,20); +# } +# else +# { +# print("Can't kill the process $process\n"); +# } +} + + +sub startTest +{ + my $libs = shift; + my $mainLib = shift; + my $openGL = ((shift)?"true":"false"); + system("$adb_tool $device_serial shell am start -n $intentName --ez needsOpenGl $openGL --es extra_libs \"$libs\" --es lib_name \"$mainLib\""); # start intent + #wait to start + return 0 unless(waitForProcess($packageName,1,10)); + #wait to stop + unless(waitForProcess($packageName,0,$time_out,5)) + { + killProcess($packageName); + return 1; + } + my $output_file = shift; + system("$adb_tool $device_serial pull /data/data/$packageName/app_files/output.xml $output_dir/$output_file"); + return 1; +} + +sub needsOpenGl +{ + my $app=$readelf_tool.shift.' |grep -e "^.*(NEEDED).*Shared library: \[libQtOpenGL\.so\]$"'; + my $res=`$app`; + chomp $res; + return $res; +} + +########### delpoy qt libs ########### +if ($deploy_qt) +{ + + pushd($src_dir_qt); + mkdir("$temp_dir/lib"); + my @libs=`find lib -name *.so`; # libs must be handled diferently + foreach (@libs) + { + chomp; + print ("cp -L $_ $temp_dir/lib\n"); + system("cp -L $_ $temp_dir/lib"); + } + system("cp -a plugins $temp_dir"); + system("cp -a imports $temp_dir"); + pushd($temp_dir); + system("find -name *.so | xargs $strip_tool --strip-unneeded"); + popd; + system("$adb_tool $device_serial shell rm -r /data/local/qt"); # remove old qt libs + system("$adb_tool $device_serial push $temp_dir /data/local/qt"); # copy newer qt libs + popd; +} + +########### build & install quadruplor ########### +reinstallQuadruplor; + +########### build qt tests and benchmarks ########### +pushd($tests_dir); +system("make distclean") if ($make_clean); +system("$qmake_path CONFIG-=QTDIR_build -r") == 0 or die "Can't run qmake\n"; #exec qmake +system("make -j$jobs") == 0 or warn "Can't build all tests\n"; #exec make +my $testsFiles=`find . -name libtst_*.so`; # only tests +foreach (split("\n",$testsFiles)) +{ + chomp; #remove white spaces + pushd(abs_path(dirname($_))); # cd to application dir + system("make INSTALL_ROOT=$temp_dir install"); # install the application to temp dir + system("$adb_tool $device_serial shell rm -r /data/data/$packageName/app_files/*"); # remove old data + system("$adb_tool $device_serial push $temp_dir /data/data/$packageName/app_files"); # copy + my $application=basename(cwd); + my $output_name=dirname($_); + $output_name =~ s/\.//; # remove first "." character + $output_name =~ s/\///; # remove first "/" character + $output_name =~ s/\//_/g; # replace all "/" with "_" + $output_name=$application unless($output_name); + $time_out=5*60/5; # 5 minutes time out for a normal test + if (-e "$temp_dir/libtst_bench_$application.so") + { + $time_out=5*60/5; # 10 minutes for a benchmark + $application = "bench_$application"; + } + + if (-e "$temp_dir/libtst_$application.so") + { + if (needsOpenGl("$temp_dir/libtst_$application.so")) + { + startTest("/data/local/qt/plugins/platforms/android/libandroidGL-$sdk_api.so", "/data/data/$packageName/app_files/libtst_$application.so", 1 + , "$output_name.xml") or warn "Can't run $application ...\n"; + } + else + { + startTest("/data/local/qt/plugins/platforms/android/libandroid-$sdk_api.so", "/data/data/$packageName/app_files/libtst_$application.so", 0 + , "$output_name.xml") or warn "Can't run $application stopping tests ...\n"; + } + } + else + { #ups this test application doesn't respect name convention + warn "$application test application doesn't respect name convention please fix it !\n"; + } + popd(); + remove_tree( $temp_dir, {keep_root => 1} ); +} +popd(); + +__END__ + +=head1 NAME + +Script to run all qt tests/benchmarks to an android device/emulator + +=head1 SYNOPSIS + +runtests.pl [options] + +=head1 OPTIONS + +=over 8 + +=item B<-s --serial = serial> + +Device serial number. May be empty if only one device is attached. + +=item B<-t --test = test_subset> + +Tests subset (e.g. benchmarks, auto, auto/qbuffer, etc.). + +=item B<-d --deploy> + +Deploy current qt libs. + +=item B<-c --clean> + +Clean tests before building them. + +=item B<-j --jobs = number> + +Make jobs when building tests. + +=item B<--sdk = sdk_path> + +Android SDK path. + +=item B<--ant = ant_tool_path> + +Ant tool path. + +=item B<--strip = strip_tool_path> + +Android strip tool path, used to deploy qt libs. + +=item B<--readelf = readelf_tool_path> + +Android readelf tool path, used to check if a test application uses qt OpenGL. + +=item B<-h --help> + +Print a brief help message and exits. + +=item B<--man> + +Prints the manual page and exits. + +=back + +=head1 DESCRIPTION + +B<This program> will run all qt tests/benchmarks to an android device/emulator. + +=cut diff --git a/tests/auto/android/src/org/qtproject/qt5/android/QtActivity.java b/tests/auto/android/src/org/qtproject/qt5/android/QtActivity.java new file mode 100644 index 0000000000..ae4ca3c30a --- /dev/null +++ b/tests/auto/android/src/org/qtproject/qt5/android/QtActivity.java @@ -0,0 +1,327 @@ +/* + Copyright (c) 2012, BogDan Vatra <bogdan@kde.org> + Contact: http://www.qt-project.org/legal + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package org.qtproject.qt5.android; + +import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; + +import org.qtproject.qt5.android.tests.R; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Rect; +import android.os.Bundle; +import android.text.method.MetaKeyKeyListener; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.KeyCharacterMap; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.Window; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; + +public class QtActivity extends Activity { + private int m_id =- 1; + private boolean softwareKeyboardIsVisible = false; + private long m_metaState; + private int m_lastChar = 0; + private boolean m_fullScreen = false; + private boolean m_started = false; + private QtSurface m_surface = null; + private boolean m_usesGL = false; + private void loadQtLibs(String[] libs, String environment, String params, String mainLib, String nativeLibDir) throws Exception + { + QtNative.loadQtLibraries(libs); + // start application + + final String envPaths = "NECESSITAS_API_LEVEL=2\tHOME=" + getDir("files", MODE_WORLD_WRITEABLE).getAbsolutePath() + + "\tTMPDIR=" + getDir("files", MODE_WORLD_WRITEABLE).getAbsolutePath() + + "\tCACHE_PATH=" + getDir("files", MODE_WORLD_WRITEABLE).getAbsolutePath(); + if (environment != null && environment.length() > 0) + environment = envPaths + "\t" + environment; + else + environment = envPaths; + + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + QtNative.startApplication(params, environment, mainLib, nativeLibDir); + m_surface.applicationStarted(m_usesGL); + m_started = true; + } + + private boolean m_quitApp = true; + private Process m_debuggerProcess = null; // debugger process + + private void startApp(final boolean firstStart) + { + try { + String qtLibs[] = getResources().getStringArray(R.array.qt_libs); + ArrayList<String> libraryList = new ArrayList<String>(); + for (int i = 0; i < qtLibs.length; i++) + libraryList.add("/data/local/qt/lib/lib" + qtLibs[i] + ".so"); + + String mainLib = null; + String nativeLibDir = null; + if (getIntent().getExtras() != null) { + if (getIntent().getExtras().containsKey("extra_libs")) { + String extra_libs = getIntent().getExtras().getString("extra_libs"); + for (String lib : extra_libs.split(":")) + libraryList.add(lib); + } + if (getIntent().getExtras().containsKey("lib_name")) { + mainLib = getIntent().getExtras().getString("lib_name"); + int slash = mainLib.lastIndexOf("/"); + if (slash >= 0) { + nativeLibDir = mainLib.substring(0, slash+1); + mainLib = mainLib.substring(slash+1+3, mainLib.length()-3); //remove lib and .so + } else { + nativeLibDir = ""; + } + } + + if (getIntent().getExtras().containsKey("needsOpenGl")) + m_usesGL = getIntent().getExtras().getBoolean("needsOpenGl"); + } else { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + System.exit(0); + } + String[] libs = new String[libraryList.size()]; + libs = libraryList.toArray(libs); + loadQtLibs(libs, "QML_IMPORT_PATH=/data/local/qt/imports\tQT_PLUGIN_PATH=/data/local/qt/plugins", + "-xml\t-silent\t-o\toutput.xml", mainLib, nativeLibDir); + } catch (Exception e) { + Log.e(QtNative.QtTAG, "Can't create main activity", e); + } + } + + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + getDir("files", MODE_WORLD_WRITEABLE); + requestWindowFeature(Window.FEATURE_NO_TITLE); + m_quitApp = true; + QtNative.setMainActivity(this); + if (null == getLastNonConfigurationInstance()) { + DisplayMetrics metrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(metrics); + QtNative.setApplicationDisplayMetrics(metrics.widthPixels, metrics.heightPixels, + metrics.widthPixels, metrics.heightPixels, + metrics.xdpi, metrics.ydpi); + } + m_surface = new QtSurface(this, m_id); + setContentView(m_surface); + if (null == getLastNonConfigurationInstance()) + startApp(true); + } + + public QtSurface getQtSurface() + { + return m_surface; + } + + @Override + public Object onRetainNonConfigurationInstance() + { + super.onRetainNonConfigurationInstance(); + m_quitApp = false; + return true; + } + + @Override + protected void onDestroy() + { + QtNative.setMainActivity(null); + super.onDestroy(); + if (m_quitApp) { + Log.i(QtNative.QtTAG, "onDestroy"); + if (m_debuggerProcess != null) + m_debuggerProcess.destroy(); + System.exit(0);// FIXME remove it or find a better way + } + QtNative.setMainActivity(null); + } + + @Override + protected void onResume() + { + // fire all lostActions + synchronized (QtNative.m_mainActivityMutex) { + Iterator<Runnable> itr = QtNative.getLostActions().iterator(); + while (itr.hasNext()) + runOnUiThread(itr.next()); + if (m_started) { + QtNative.clearLostActions(); + QtNative.updateWindow(); + } + } + super.onResume(); + } + + public void redrawWindow(int left, int top, int right, int bottom) + { + m_surface.drawBitmap(new Rect(left, top, right, bottom)); + } + + public void setFullScreen(boolean enterFullScreen) + { + if (m_fullScreen == enterFullScreen) + return; + if (m_fullScreen = enterFullScreen) + getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + else + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + + @Override + protected void onSaveInstanceState(Bundle outState) + { + super.onSaveInstanceState(outState); + outState.putBoolean("FullScreen", m_fullScreen); + outState.putBoolean("Started", m_started); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) + { + super.onRestoreInstanceState(savedInstanceState); + setFullScreen(savedInstanceState.getBoolean("FullScreen")); + m_started = savedInstanceState.getBoolean("Started"); + if (m_started) + m_surface.applicationStarted(true); + } + + public void showSoftwareKeyboard() + { + softwareKeyboardIsVisible = true; + InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); + } + + public void resetSoftwareKeyboard() + { + } + + public void hideSoftwareKeyboard() + { + if (softwareKeyboardIsVisible) { + InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); + imm.toggleSoftInput(0, 0); + } + softwareKeyboardIsVisible = false; + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) + { + if (m_started && event.getAction() == KeyEvent.ACTION_MULTIPLE && + event.getCharacters() != null && + event.getCharacters().length() == 1 && + event.getKeyCode() == 0) { + Log.i(QtNative.QtTAG, "dispatchKeyEvent at MULTIPLE with one character: " + event.getCharacters()); + QtNative.keyDown(0, event.getCharacters().charAt(0), event.getMetaState()); + QtNative.keyUp(0, event.getCharacters().charAt(0), event.getMetaState()); + } + + return super.dispatchKeyEvent(event); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) + { + if (!m_started) + return false; + m_metaState = MetaKeyKeyListener.handleKeyDown(m_metaState, keyCode, event); + int c = event.getUnicodeChar(MetaKeyKeyListener.getMetaState(m_metaState)); + int lc = c; + m_metaState = MetaKeyKeyListener.adjustMetaAfterKeypress(m_metaState); + + if ((c & KeyCharacterMap.COMBINING_ACCENT) != 0) { + c = c & KeyCharacterMap.COMBINING_ACCENT_MASK; + int composed = KeyEvent.getDeadChar(m_lastChar, c); + c = composed; + } + m_lastChar = lc; + if (keyCode != KeyEvent.KEYCODE_BACK) + QtNative.keyDown(keyCode, c, event.getMetaState()); + return true; + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) + { + if (!m_started) + return false; + m_metaState = MetaKeyKeyListener.handleKeyUp(m_metaState, keyCode, event); + QtNative.keyUp(keyCode, event.getUnicodeChar(), event.getMetaState()); + return true; + } + + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + } + +/* public boolean onCreateOptionsMenu(Menu menu) + { + QtNative.createOptionsMenu(menu); + try { + return onPrepareOptionsMenu(menu); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public boolean onPrepareOptionsMenu(Menu menu) + { + QtNative.prepareOptionsMenu(menu); + try { + return (Boolean) onPrepareOptionsMenu(menu); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public boolean onOptionsItemSelected(MenuItem item) + { + return QtNative.optionsItemSelected(item.getGroupId(), item.getItemId()); + }*/ +} diff --git a/tests/auto/android/src/org/qtproject/qt5/android/QtInputConnection.java b/tests/auto/android/src/org/qtproject/qt5/android/QtInputConnection.java new file mode 100644 index 0000000000..e69a03061b --- /dev/null +++ b/tests/auto/android/src/org/qtproject/qt5/android/QtInputConnection.java @@ -0,0 +1,209 @@ +/* + Copyright (c) 2012, BogDan Vatra <bogdan@kde.org> + Contact: http://www.qt-project.org/legal + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package org.qtproject.qt5.android; + +import android.content.Context; +import android.content.Intent; +import android.text.Editable; +import android.text.InputFilter; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.view.inputmethod.BaseInputConnection; +import android.view.inputmethod.CompletionInfo; +import android.view.inputmethod.ExtractedText; +import android.view.inputmethod.ExtractedTextRequest; +import android.view.inputmethod.InputMethodManager; + +class QtExtractedText +{ + public int partialEndOffset; + public int partialStartOffset; + public int selectionEnd; + public int selectionStart; + public int startOffset; + public String text; +} + +class QtNativeInputConnection +{ + static native boolean commitText(String text, int newCursorPosition); + static native boolean commitCompletion(String text, int position); + static native boolean deleteSurroundingText(int leftLength, int rightLength); + static native boolean finishComposingText(); + static native int getCursorCapsMode(int reqModes); + static native QtExtractedText getExtractedText(int hintMaxChars, int hintMaxLines, int flags); + static native String getSelectedText(int flags); + static native String getTextAfterCursor(int length, int flags); + static native String getTextBeforeCursor(int length, int flags); + static native boolean setComposingText(String text, int newCursorPosition); + static native boolean setSelection(int start, int end); + static native boolean selectAll(); + static native boolean cut(); + static native boolean copy(); + static native boolean copyURL(); + static native boolean paste(); +} + +public class QtInputConnection extends BaseInputConnection +{ + private static final int ID_SELECT_ALL = android.R.id.selectAll; + private static final int ID_START_SELECTING_TEXT = android.R.id.startSelectingText; + private static final int ID_STOP_SELECTING_TEXT = android.R.id.stopSelectingText; + private static final int ID_CUT = android.R.id.cut; + private static final int ID_COPY = android.R.id.copy; + private static final int ID_PASTE = android.R.id.paste; + private static final int ID_COPY_URL = android.R.id.copyUrl; + private static final int ID_SWITCH_INPUT_METHOD = android.R.id.switchInputMethod; + private static final int ID_ADD_TO_DICTIONARY = android.R.id.addToDictionary; + View m_view; + + public QtInputConnection(View targetView) + { + super(targetView, true); + m_view = targetView; + } + + @Override + public boolean beginBatchEdit() + { + return true; + } + + @Override + public boolean endBatchEdit() + { + return true; + } + + @Override + public boolean commitCompletion(CompletionInfo text) + { + return QtNativeInputConnection.commitCompletion(text.getText().toString(), text.getPosition()); + } + + @Override + public boolean commitText(CharSequence text, int newCursorPosition) + { + return QtNativeInputConnection.commitText(text.toString(), newCursorPosition); + } + + @Override + public boolean deleteSurroundingText(int leftLength, int rightLength) + { + return QtNativeInputConnection.deleteSurroundingText(leftLength, rightLength); + } + + @Override + public boolean finishComposingText() + { + return QtNativeInputConnection.finishComposingText(); + } + + @Override + public int getCursorCapsMode(int reqModes) + { + return QtNativeInputConnection.getCursorCapsMode(reqModes); + } + + @Override + public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) + { + QtExtractedText qExtractedText = QtNativeInputConnection.getExtractedText(request.hintMaxChars, request.hintMaxLines, flags); + ExtractedText extractedText = new ExtractedText(); + extractedText.partialEndOffset = qExtractedText.partialEndOffset; + extractedText.partialStartOffset = qExtractedText.partialStartOffset; + extractedText.selectionEnd = qExtractedText.selectionEnd; + extractedText.selectionStart = qExtractedText.selectionStart; + extractedText.startOffset = qExtractedText.startOffset; + extractedText.text = qExtractedText.text; + return extractedText; + } + + public CharSequence getSelectedText(int flags) + { + return QtNativeInputConnection.getSelectedText(flags); + } + + @Override + public CharSequence getTextAfterCursor(int length, int flags) + { + return QtNativeInputConnection.getTextAfterCursor(length, flags); + } + + @Override + public CharSequence getTextBeforeCursor(int length, int flags) + { + return QtNativeInputConnection.getTextBeforeCursor(length, flags); + } + + @Override + public boolean performContextMenuAction(int id) + { + switch (id) { + case ID_SELECT_ALL: + return QtNativeInputConnection.selectAll(); + case ID_COPY: + return QtNativeInputConnection.copy(); + case ID_COPY_URL: + return QtNativeInputConnection.copyURL(); + case ID_CUT: + return QtNativeInputConnection.cut(); + case ID_PASTE: + return QtNativeInputConnection.paste(); + + case ID_SWITCH_INPUT_METHOD: + InputMethodManager imm = (InputMethodManager)m_view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm != null) { + imm.showInputMethodPicker(); + } + return true; + + case ID_ADD_TO_DICTIONARY: +// TODO +// String word = m_editable.subSequence(0, m_editable.length()).toString(); +// if (word != null) { +// Intent i = new Intent("com.android.settings.USER_DICTIONARY_INSERT"); +// i.putExtra("word", word); +// i.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); +// m_view.getContext().startActivity(i); +// } + return true; + } + return super.performContextMenuAction(id); + } + + @Override + public boolean setComposingText(CharSequence text, int newCursorPosition) { + return QtNativeInputConnection.setComposingText(text.toString(), newCursorPosition); + } + + @Override + public boolean setSelection(int start, int end) { + return QtNativeInputConnection.setSelection(start, end); + } +} diff --git a/tests/auto/android/src/org/qtproject/qt5/android/QtNative.java b/tests/auto/android/src/org/qtproject/qt5/android/QtNative.java new file mode 100644 index 0000000000..8faeabe5b0 --- /dev/null +++ b/tests/auto/android/src/org/qtproject/qt5/android/QtNative.java @@ -0,0 +1,421 @@ +/* + Copyright (c) 2012, BogDan Vatra <bogdan@kde.org> + Contact: http://www.qt-project.org/legal + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package org.qtproject.qt5.android; + +import java.io.File; +import java.util.ArrayList; + +import android.app.Activity; +import android.app.Application; +import android.content.Intent; +import android.net.Uri; +import android.util.Log; +import android.view.Menu; +import android.view.MotionEvent; + +public class QtNative extends Application +{ + private static QtActivity m_mainActivity = null; + private static QtSurface m_mainView = null; + public static Object m_mainActivityMutex = new Object(); // mutex used to synchronize runnable operations + + public static final String QtTAG = "Qt JAVA"; // string used for Log.x + private static ArrayList<Runnable> m_lostActions = new ArrayList<Runnable>(); // a list containing all actions which could not be performed (e.g. the main activity is destroyed, etc.) + private static boolean m_started = false; + private static int m_displayMetricsScreenWidthPixels = 0; + private static int m_displayMetricsScreenHeightPixels = 0; + private static int m_displayMetricsDesktopWidthPixels = 0; + private static int m_displayMetricsDesktopHeightPixels = 0; + private static double m_displayMetricsXDpi = .0; + private static double m_displayMetricsYDpi = .0; + private static int m_oldx, m_oldy; + private static final int m_moveThreshold = 0; + + public static ClassLoader classLoader() + { + return m_mainActivity.getClassLoader(); + } + + public static Activity activity() + { + return m_mainActivity; + } + + public static QtSurface mainView() + { + return m_mainView; + } + + public static void openURL(String url) + { + Uri uri = Uri.parse(url); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + activity().startActivity(intent); + } + + // this method loads full path libs + public static void loadQtLibraries(String[] libraries) + { + if (libraries == null) + return; + + for (int i = 0; i < libraries.length; i++) { + try { + File f = new File(libraries[i]); + if (f.exists()) + System.load(libraries[i]); + } catch (SecurityException e) { + Log.i(QtTAG, "Can't load '" + libraries[i] + "'", e); + } catch (Exception e) { + Log.i(QtTAG, "Can't load '" + libraries[i] + "'", e); + } + } + } + + // this method loads bundled libs by name. + public static void loadBundledLibraries(String[] libraries) + { + for (int i = 0; i < libraries.length; i++) { + try { + System.loadLibrary(libraries[i]); + } catch (UnsatisfiedLinkError e) { + Log.i(QtTAG, "Can't load '" + libraries[i] + "'", e); + } catch (SecurityException e) { + Log.i(QtTAG, "Can't load '" + libraries[i] + "'", e); + } catch (Exception e) { + Log.i(QtTAG, "Can't load '" + libraries[i] + "'", e); + } + } + } + + public static void setMainActivity(QtActivity qtMainActivity) + { + synchronized (m_mainActivityMutex) { + m_mainActivity = qtMainActivity; + } + } + public static void setMainView(QtSurface qtSurface) + { + synchronized (m_mainActivityMutex) { + m_mainView = qtSurface; + } + } + + static public ArrayList<Runnable> getLostActions() + { + return m_lostActions; + } + + static public void clearLostActions() + { + m_lostActions.clear(); + } + + private static boolean runAction(Runnable action) + { + synchronized (m_mainActivityMutex) { + if (m_mainActivity == null) + m_lostActions.add(action); + else + m_mainActivity.runOnUiThread(action); + return m_mainActivity != null; + } + } + + public static boolean startApplication(String params, String environment, String mainLibrary, String nativeLibraryDir) throws Exception + { + File f = new File(nativeLibraryDir+"lib"+mainLibrary+".so"); + if (!f.exists()) + throw new Exception("Can't find main library '" + mainLibrary + "'"); + + if (params == null) + params = "-platform\tandroid"; + + boolean res = false; + synchronized (m_mainActivityMutex) { + res = startQtAndroidPlugin(); + setDisplayMetrics(m_displayMetricsScreenWidthPixels, + m_displayMetricsScreenHeightPixels, + m_displayMetricsDesktopWidthPixels, + m_displayMetricsDesktopHeightPixels, + m_displayMetricsXDpi, + m_displayMetricsYDpi); + startQtApplication(f.getAbsolutePath()+"\t"+params, environment); + m_started = true; + } + return res; + } + + public static void setApplicationDisplayMetrics(int screenWidthPixels, + int screenHeightPixels, int desktopWidthPixels, + int desktopHeightPixels, double XDpi, double YDpi) + { + /* Fix buggy dpi report */ + if (XDpi < android.util.DisplayMetrics.DENSITY_LOW) + XDpi = android.util.DisplayMetrics.DENSITY_LOW; + if (YDpi < android.util.DisplayMetrics.DENSITY_LOW) + YDpi = android.util.DisplayMetrics.DENSITY_LOW; + + synchronized (m_mainActivityMutex) { + if (m_started) { + setDisplayMetrics(screenWidthPixels, screenHeightPixels, desktopWidthPixels, desktopHeightPixels, XDpi, YDpi); + } else { + m_displayMetricsScreenWidthPixels = screenWidthPixels; + m_displayMetricsScreenHeightPixels = screenHeightPixels; + m_displayMetricsDesktopWidthPixels = desktopWidthPixels; + m_displayMetricsDesktopHeightPixels = desktopHeightPixels; + m_displayMetricsXDpi = XDpi; + m_displayMetricsYDpi = YDpi; + } + } + } + + public static void pauseApplication() + { + synchronized (m_mainActivityMutex) { + if (m_started) + pauseQtApp(); + } + } + + public static void resumeApplication() + { + synchronized (m_mainActivityMutex) { + if (m_started) { + resumeQtApp(); + updateWindow(); + } + } + } + // application methods + public static native void startQtApplication(String params, String env); + public static native void pauseQtApp(); + public static native void resumeQtApp(); + public static native boolean startQtAndroidPlugin(); + public static native void quitQtAndroidPlugin(); + public static native void terminateQt(); + // application methods + + private static void quitApp() + { + m_mainActivity.finish(); + } + + private static void redrawSurface(final int left, final int top, final int right, final int bottom ) + { + runAction(new Runnable() { + @Override + public void run() { + m_mainActivity.redrawWindow(left, top, right, bottom); + } + }); + } + + @Override + public void onTerminate() + { + if (m_started) + terminateQt(); + super.onTerminate(); + } + + + static public void sendTouchEvent(MotionEvent event, int id) + { + switch (event.getAction()) { + case MotionEvent.ACTION_UP: + mouseUp(id,(int) event.getX(), (int) event.getY()); + break; + + case MotionEvent.ACTION_DOWN: + mouseDown(id,(int) event.getX(), (int) event.getY()); + m_oldx = (int) event.getX(); + m_oldy = (int) event.getY(); + break; + + case MotionEvent.ACTION_MOVE: + int dx = (int) (event.getX() - m_oldx); + int dy = (int) (event.getY() - m_oldy); + if (Math.abs(dx) > m_moveThreshold || Math.abs(dy) > m_moveThreshold) { + mouseMove(id,(int) event.getX(), (int) event.getY()); + m_oldx = (int) event.getX(); + m_oldy = (int) event.getY(); + } + break; + } + } + + static public void sendTrackballEvent(MotionEvent event, int id) + { + switch (event.getAction()) { + case MotionEvent.ACTION_UP: + mouseUp(id, (int) event.getX(), (int) event.getY()); + break; + + case MotionEvent.ACTION_DOWN: + mouseDown(id, (int) event.getX(), (int) event.getY()); + m_oldx = (int) event.getX(); + m_oldy = (int) event.getY(); + break; + + case MotionEvent.ACTION_MOVE: + int dx = (int) (event.getX() - m_oldx); + int dy = (int) (event.getY() - m_oldy); + if (Math.abs(dx) > 5 || Math.abs(dy) > 5) { + mouseMove(id, (int) event.getX(), (int) event.getY()); + m_oldx = (int) event.getX(); + m_oldy = (int) event.getY(); + } + break; + } + } + + + private static void showSoftwareKeyboard(final int x, final int y + , final int width, final int height + , final int inputHints ) + { + runAction(new Runnable() { + @Override + public void run() { + m_mainActivity.showSoftwareKeyboard(); + } + }); + } + + private static void resetSoftwareKeyboard() + { + runAction(new Runnable() { + @Override + public void run() { + m_mainActivity.resetSoftwareKeyboard(); + } + }); + } + + private static void hideSoftwareKeyboard() + { + runAction(new Runnable() { + @Override + public void run() { + m_mainActivity.hideSoftwareKeyboard(); + } + }); + } + + private static void setFullScreen(final boolean fullScreen) + { + runAction(new Runnable() { + @Override + public void run() { + m_mainActivity.setFullScreen(fullScreen); + updateWindow(); + } + }); + } + + // screen methods + public static native void setDisplayMetrics(int screenWidthPixels, + int screenHeightPixels, int desktopWidthPixels, + int desktopHeightPixels, double XDpi, double YDpi); + // screen methods + + private static void showOptionsMenu() + { + runAction(new Runnable() { + @Override + public void run() { + if (m_mainActivity != null) + m_mainActivity.openOptionsMenu(); + } + }); + } + + private static void hideOptionsMenu() + { + runAction(new Runnable() { + @Override + public void run() { + if (m_mainActivity != null) + m_mainActivity.closeOptionsMenu(); + } + }); + } + + private static void showContextMenu() + { + runAction(new Runnable() { + @Override + public void run() { + if (m_mainActivity != null) + m_mainActivity.openContextMenu(m_mainView); + } + }); + } + + private static void hideContextMenu() + { + runAction(new Runnable() { + @Override + public void run() { + if (m_mainActivity != null) + m_mainActivity.closeContextMenu(); + } + }); + } + + // pointer methods + public static native void mouseDown(int winId, int x, int y); + public static native void mouseUp(int winId, int x, int y); + public static native void mouseMove(int winId, int x, int y); + public static native void touchBegin(int winId); + public static native void touchAdd(int winId, int pointerId, int action, boolean primary, int x, int y, float size, float pressure); + public static native void touchEnd(int winId, int action); + // pointer methods + + // keyboard methods + public static native void keyDown(int key, int unicode, int modifier); + public static native void keyUp(int key, int unicode, int modifier); + // keyboard methods + + // surface methods + public static native void destroySurface(); + public static native void setSurface(Object surface); + public static native void lockSurface(); + public static native void unlockSurface(); + // surface methods + + // window methods + public static native void updateWindow(); + // window methods + + // options menu methods + public static native void createOptionsMenu(Menu menu); + public static native boolean prepareOptionsMenu(Menu menu); + public static native boolean optionsItemSelected(int groupId, int itemId); + // options menu methods +} diff --git a/tests/auto/android/src/org/qtproject/qt5/android/QtSurface.java b/tests/auto/android/src/org/qtproject/qt5/android/QtSurface.java new file mode 100644 index 0000000000..7e7db031ec --- /dev/null +++ b/tests/auto/android/src/org/qtproject/qt5/android/QtSurface.java @@ -0,0 +1,163 @@ +/* + Copyright (c) 2012, BogDan Vatra <bogdan@kde.org> + Contact: http://www.qt-project.org/legal + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package org.qtproject.qt5.android; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.MotionEvent; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +public class QtSurface extends SurfaceView implements SurfaceHolder.Callback +{ + private Bitmap m_bitmap=null; + private boolean m_started = false; + private boolean m_usesGL = false; + public QtSurface(Context context, int id) + { + super(context); + setFocusable(true); + getHolder().addCallback(this); + getHolder().setType(SurfaceHolder.SURFACE_TYPE_GPU); + setId(id); + } + + public void applicationStarted(boolean usesGL) + { + m_started = true; + m_usesGL = usesGL; + if (getWidth() < 1 || getHeight() < 1) + return; + if (m_usesGL) { + QtNative.setSurface(getHolder().getSurface()); + } else { + QtNative.lockSurface(); + QtNative.setSurface(null); + m_bitmap=Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.RGB_565); + QtNative.setSurface(m_bitmap); + QtNative.unlockSurface(); + } + } + + @Override + public void surfaceCreated(SurfaceHolder holder) + { + DisplayMetrics metrics = new DisplayMetrics(); + ((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(metrics); + QtNative.setApplicationDisplayMetrics(metrics.widthPixels, + metrics.heightPixels, getWidth(), getHeight(), metrics.xdpi, metrics.ydpi); + + if (m_usesGL) + holder.setFormat(PixelFormat.RGBA_8888); + else + holder.setFormat(PixelFormat.RGB_565); + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) + { + Log.i(QtNative.QtTAG,"surfaceChanged: "+width+","+height); + if (width < 1 || height < 1) + return; + + DisplayMetrics metrics = new DisplayMetrics(); + ((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(metrics); + QtNative.setApplicationDisplayMetrics(metrics.widthPixels, + metrics.heightPixels, width, height, metrics.xdpi, metrics.ydpi); + + if (!m_started) + return; + + if (m_usesGL) { + QtNative.setSurface(holder.getSurface()); + } else { + QtNative.lockSurface(); + QtNative.setSurface(null); + m_bitmap=Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); + QtNative.setSurface(m_bitmap); + QtNative.unlockSurface(); + QtNative.updateWindow(); + } + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) + { + Log.i(QtNative.QtTAG,"surfaceDestroyed "); + if (m_usesGL) { + QtNative.destroySurface(); + } else { + if (!m_started) + return; + + QtNative.lockSurface(); + QtNative.setSurface(null); + QtNative.unlockSurface(); + } + } + + public void drawBitmap(Rect rect) + { + if (!m_started) + return; + QtNative.lockSurface(); + if (null != m_bitmap) { + try { + Canvas cv=getHolder().lockCanvas(rect); + cv.drawBitmap(m_bitmap, rect, rect, null); + getHolder().unlockCanvasAndPost(cv); + } catch (Exception e) { + Log.e(QtNative.QtTAG, "Can't create main activity", e); + } + } + QtNative.unlockSurface(); + } + + @Override + public boolean onTouchEvent(MotionEvent event) + { + if (!m_started) + return false; + QtNative.sendTouchEvent(event, getId()); + return true; + } + + @Override + public boolean onTrackballEvent(MotionEvent event) + { + if (!m_started) + return false; + QtNative.sendTrackballEvent(event, getId()); + return true; + } +} diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 6ff0734186..758d89ab72 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -20,5 +20,7 @@ wince*: SUBDIRS -= printsupport cross_compile: SUBDIRS -= tools !qtHaveModule(opengl): SUBDIRS -= opengl !unix|embedded|!qtHaveModule(dbus): SUBDIRS -= dbus -!qtHaveModule(widgets): SUBDIRS -= widgets printsupport +!qtHaveModule(widgets): SUBDIRS -= widgets +!qtHaveModule(printsupport): SUBDIRS -= printsupport !qtHaveModule(concurrent): SUBDIRS -= concurrent +!qtHaveModule(network): SUBDIRS -= network diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt index 6da0c9bfa6..677e6a6330 100644 --- a/tests/auto/cmake/CMakeLists.txt +++ b/tests/auto/cmake/CMakeLists.txt @@ -51,9 +51,11 @@ if(NOT ${CMAKE_VERSION} VERSION_LESS 2.8.9) # Requires INCLUDE_DIRECTORIES target property in CMake 2.8.8 # and POSITION_INDEPENDENT_CODE target property in 2.8.9 expect_pass(test_use_modules_function) + expect_pass(test_umbrella_config) else() - message("CMake version older than 2.8.9 (Found ${CMAKE_VERSION}). Not running test \"test_use_modules_function\"") + message("CMake version older than 2.8.9 (Found ${CMAKE_VERSION}). Not running test \"test_use_modules_function\" or \"test_umbrella_config\"") endif() + expect_pass(test_wrap_cpp_and_resources) expect_pass(test_dependent_modules) expect_fail(test_add_resource_options) diff --git a/tests/auto/cmake/test_umbrella_config/CMakeLists.txt b/tests/auto/cmake/test_umbrella_config/CMakeLists.txt new file mode 100644 index 0000000000..a8fc2b53ed --- /dev/null +++ b/tests/auto/cmake/test_umbrella_config/CMakeLists.txt @@ -0,0 +1,20 @@ + +cmake_minimum_required(VERSION 2.8) + +project(test_umbrella_config) + +add_subdirectory(components_found) + +if (Qt5_FOUND) + message(SEND_ERROR "Qt5_FOUND variable leaked!") +endif() + +if (Qt5Core_FOUND) + message(SEND_ERROR "Qt5Core_FOUND variable leaked!") +endif() + +if (TARGET Qt5::Core) + message(SEND_ERROR "Qt5::Core target leaked!") +endif() + +add_subdirectory(components_not_found) diff --git a/tests/auto/cmake/test_umbrella_config/components_found/CMakeLists.txt b/tests/auto/cmake/test_umbrella_config/components_found/CMakeLists.txt new file mode 100644 index 0000000000..91cb623deb --- /dev/null +++ b/tests/auto/cmake/test_umbrella_config/components_found/CMakeLists.txt @@ -0,0 +1,18 @@ + +# The module finds its dependencies +find_package(Qt5 + COMPONENTS Core + OPTIONAL_COMPONENTS DoesNotExist +) + +if (NOT Qt5_FOUND) + message(SEND_ERROR "Qt5 umbrella package not found!") +endif() + +if (NOT Qt5Core_FOUND) + message(SEND_ERROR "Qt5Core package not found!") +endif() + +if (Qt5DoesNotExist_FOUND) + message(SEND_ERROR "Non-existent package found!") +endif() diff --git a/tests/auto/cmake/test_umbrella_config/components_not_found/CMakeLists.txt b/tests/auto/cmake/test_umbrella_config/components_not_found/CMakeLists.txt new file mode 100644 index 0000000000..424c3e3445 --- /dev/null +++ b/tests/auto/cmake/test_umbrella_config/components_not_found/CMakeLists.txt @@ -0,0 +1,17 @@ + +# The module finds its dependencies +find_package(Qt5 + COMPONENTS Core DoesNotExist +) + +if (Qt5_FOUND) + message(SEND_ERROR "Qt5 umbrella package found, though it should not be!") +endif() + +if (NOT Qt5Core_FOUND) + message(SEND_ERROR "Qt5Core package not found!") +endif() + +if (Qt5DoesNotExist_FOUND) + message(SEND_ERROR "Non-existent package found!") +endif() diff --git a/tests/auto/corelib/animation/qsequentialanimationgroup/tst_qsequentialanimationgroup.cpp b/tests/auto/corelib/animation/qsequentialanimationgroup/tst_qsequentialanimationgroup.cpp index ccc23851b7..51f07993cd 100644 --- a/tests/auto/corelib/animation/qsequentialanimationgroup/tst_qsequentialanimationgroup.cpp +++ b/tests/auto/corelib/animation/qsequentialanimationgroup/tst_qsequentialanimationgroup.cpp @@ -44,7 +44,6 @@ #include <QtCore/qsequentialanimationgroup.h> Q_DECLARE_METATYPE(QAbstractAnimation::State) -Q_DECLARE_METATYPE(QAbstractAnimation*) class tst_QSequentialAnimationGroup : public QObject { @@ -84,7 +83,6 @@ private slots: void tst_QSequentialAnimationGroup::initTestCase() { qRegisterMetaType<QAbstractAnimation::State>("QAbstractAnimation::State"); - qRegisterMetaType<QAbstractAnimation*>("QAbstractAnimation*"); } void tst_QSequentialAnimationGroup::construction() diff --git a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp index 6c566e017b..b5f736cfbb 100644 --- a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp +++ b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp @@ -84,6 +84,7 @@ private slots: void utfHeaders_data(); void utfHeaders(); + void codecForHtml_data(); void codecForHtml(); void codecForUtfText_data(); @@ -1853,23 +1854,81 @@ void tst_QTextCodec::utfHeaders() } } -void tst_QTextCodec::codecForHtml() +void tst_QTextCodec::codecForHtml_data() { - QByteArray html("<html><head></head><body>blah</body></html>"); + QTest::addColumn<QByteArray>("html"); + QTest::addColumn<int>("defaultCodecMib"); + QTest::addColumn<int>("expectedMibEnum"); - QCOMPARE(QTextCodec::codecForHtml(html)->mibEnum(), 4); // latin 1 + int noDefault = -1; + int fallback = 4; // latin 1 + QByteArray html = "<html><head></head><body>blah</body></html>"; + QTest::newRow("no charset, latin 1") << html << noDefault << fallback; - QCOMPARE(QTextCodec::codecForHtml(html, QTextCodec::codecForMib(106))->mibEnum(), 106); // UTF-8 + QTest::newRow("no charset, default UTF-8") << html << 106 << 106; html = "<html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=ISO-8859-15\" /></head></html>"; - QCOMPARE(QTextCodec::codecForHtml(html, QTextCodec::codecForMib(106))->mibEnum(), 111); // latin 15 + QTest::newRow("latin 15, default UTF-8") << html << 106 << 111; html = "<html><head><meta content=\"text/html; charset=ISO-8859-15\" http-equiv=\"content-type\" /></head></html>"; - QCOMPARE(QTextCodec::codecForHtml(html, QTextCodec::codecForMib(106))->mibEnum(), 111); // latin 15 + QTest::newRow("latin 15, default UTF-8 (#2)") << html << 106 << 111; + + html = "<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=9,chrome=1\"><title>Test</title></head>"; + QTest::newRow("UTF-8, no default") << html << noDefault << 106; + + html = "<!DOCTYPE html><html><head><meta charset=\"ISO_8859-1:1987\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=9,chrome=1\"><title>Test</title></head>"; + QTest::newRow("latin 1, no default") << html << noDefault << 4; + + html = "<!DOCTYPE html><html><head><meta http-equiv=\"X-UA-Compatible\" content=\"IE=9,chrome=1\"><meta charset=\"utf-8\"><title>Test</title></head>"; + QTest::newRow("UTF-8, no default (#2)") << html << noDefault << 106; + + html = "<html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8/></head></html>"; + QTest::newRow("UTF-8, no quotes") << html << noDefault << 106; + + html = "<html><head><meta http-equiv=\"content-type\" content=\"text/html; charset='UTF-8'/></head></html>"; + QTest::newRow("UTF-8, single quotes") << html << noDefault << 106; + + html = "<!DOCTYPE html><html><head><meta charset=utf-8><title>Test</title></head>"; + QTest::newRow("UTF-8, > terminator") << html << noDefault << 106; + + html = "<!DOCTYPE html><html><head><meta charset= utf-8 ><title>Test</title></head>"; + QTest::newRow("UTF-8, > terminator with spaces") << html << noDefault << 106; + + html = "<!DOCTYPE html><html><head><meta charset= utf/8 ><title>Test</title></head>"; + QTest::newRow("UTF-8, > teminator with early backslash)") << html << noDefault << 106; + // Test invalid charsets. html = "<html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=invalid-foo\" /></head></html>"; - QCOMPARE(QTextCodec::codecForHtml(html, QTextCodec::codecForMib(106))->mibEnum(), 106); // UTF-8 - QCOMPARE(QTextCodec::codecForHtml(html)->mibEnum(), 4); // latin 1 + QTest::newRow("invalid charset, no default") << html << noDefault << fallback; + QTest::newRow("invalid charset, default UTF-8") << html << 106 << 106; + + html = "<!DOCTYPE html><html><head><meta http-equiv=\"X-UA-Compatible\" content=\"IE=9,chrome=1\"><meta charset=\""; + html.prepend(QByteArray().fill(' ', 512 - html.size())); + QTest::newRow("invalid charset (large header)") << html << noDefault << fallback; + + html = "<!DOCTYPE html><html><head><meta http-equiv=\"X-UA-Compatible\" content=\"IE=9,chrome=1\"><meta charset=\"utf-8"; + QTest::newRow("invalid charset (no closing double quote)") << html << noDefault << fallback; + + html = "<!DOCTYPE html><html><head><meta http-equiv=\"X-UA-Compatible\" content=\"IE=9,chrome=1\"><meta charset='utf-8"; + QTest::newRow("invalid charset (no closing single quote)") << html << noDefault << fallback; + + html = "<!DOCTYPE html><html><head><meta charset=utf-8 foo=bar><title>Test</title></head>"; + QTest::newRow("invalid (space terminator)") << html << noDefault << fallback; + + html = "<!DOCTYPE html><html><head><meta charset=\" utf' 8 /><title>Test</title></head>"; + QTest::newRow("invalid charset, early terminator (')") << html << noDefault << fallback; +} + +void tst_QTextCodec::codecForHtml() +{ + QFETCH(QByteArray, html); + QFETCH(int, defaultCodecMib); + QFETCH(int, expectedMibEnum); + + if (defaultCodecMib != -1) + QCOMPARE(QTextCodec::codecForHtml(html, QTextCodec::codecForMib(defaultCodecMib))->mibEnum(), expectedMibEnum); + else // Test one parameter version when there is no default codec. + QCOMPARE(QTextCodec::codecForHtml(html)->mibEnum(), expectedMibEnum); } void tst_QTextCodec::codecForUtfText_data() diff --git a/tests/auto/corelib/global/global.pro b/tests/auto/corelib/global/global.pro index 5489b8330d..c05905bd15 100644 --- a/tests/auto/corelib/global/global.pro +++ b/tests/auto/corelib/global/global.pro @@ -7,4 +7,6 @@ SUBDIRS=\ qnumeric \ qrand \ qlogging \ - qtendian + qtendian \ + qglobalstatic \ + diff --git a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp index a4aca82aa9..ef41ef8801 100644 --- a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp +++ b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp @@ -75,6 +75,13 @@ void tst_QGetPutEnv::getSetCheck() QVERIFY(result == "supervalue"); qputenv(varName,QByteArray()); + + // Now test qunsetenv + QVERIFY(qunsetenv(varName)); + QVERIFY(!qEnvironmentVariableIsSet(varName)); + QVERIFY(qEnvironmentVariableIsEmpty(varName)); + result = qgetenv(varName); + QCOMPARE(result, QByteArray()); } QTEST_MAIN(tst_QGetPutEnv) diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp index f54af657c0..3696ee264f 100644 --- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp +++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp @@ -55,6 +55,8 @@ private slots: void checkptr(); void qstaticassert(); void qConstructorFunction(); + void qCoreAppStartupFunction(); + void qCoreAppStartupFunctionRestart(); void isEnum(); void qAlignOf(); }; @@ -303,6 +305,33 @@ void tst_QGlobal::qConstructorFunction() QCOMPARE(qConstructorFunctionValue, 123); } +static int qStartupFunctionValue; +static void myStartupFunc() +{ + Q_ASSERT(QCoreApplication::instance()); + if (QCoreApplication::instance()) + qStartupFunctionValue += 124; +} + +Q_COREAPP_STARTUP_FUNCTION(myStartupFunc) + +void tst_QGlobal::qCoreAppStartupFunction() +{ + QCOMPARE(qStartupFunctionValue, 0); + int argc = 1; + char *argv[] = { const_cast<char*>("tst_qglobal") }; + QCoreApplication app(argc, argv); + QCOMPARE(qStartupFunctionValue, 124); +} + +void tst_QGlobal::qCoreAppStartupFunctionRestart() +{ + qStartupFunctionValue = 0; + qCoreAppStartupFunction(); + qStartupFunctionValue = 0; + qCoreAppStartupFunction(); +} + struct isEnum_A { int n_; }; @@ -532,5 +561,5 @@ void tst_QGlobal::qAlignOf() #undef TEST_AlignOf_RValueRef #undef TEST_AlignOf_impl -QTEST_MAIN(tst_QGlobal) +QTEST_APPLESS_MAIN(tst_QGlobal) #include "tst_qglobal.moc" diff --git a/tests/auto/corelib/global/qglobalstatic/qglobalstatic.pro b/tests/auto/corelib/global/qglobalstatic/qglobalstatic.pro new file mode 100644 index 0000000000..21cab8f67d --- /dev/null +++ b/tests/auto/corelib/global/qglobalstatic/qglobalstatic.pro @@ -0,0 +1,12 @@ +QT += testlib core-private + +QT -= gui + +TARGET = tst_qglobalstatic +CONFIG += console +CONFIG -= app_bundle +CONFIG += exceptions + +SOURCES += tst_qglobalstatic.cpp +DEFINES += SRCDIR=\\\"$$PWD/\\\" +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp b/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp new file mode 100644 index 0000000000..131b37f821 --- /dev/null +++ b/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp @@ -0,0 +1,236 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Thiago Macieira <thiago@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QThread> +#include <QtTest/QtTest> + +class tst_QGlobalStatic : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void beforeInitialization(); + void api(); + void constVolatile(); + void exception(); + void threadedException(); + void threadStressTest(); + void afterDestruction(); +}; + +Q_GLOBAL_STATIC_WITH_ARGS(const int, constInt, (42)) +Q_GLOBAL_STATIC_WITH_ARGS(volatile int, volatileInt, (-47)) + +void otherFunction() +{ + // never called + constInt(); + volatileInt(); +} + +// do not initialize the following Q_GLOBAL_STATIC +Q_GLOBAL_STATIC(int, checkedBeforeInitialization) +void tst_QGlobalStatic::beforeInitialization() +{ + QVERIFY(!checkedBeforeInitialization.exists()); + QVERIFY(!checkedBeforeInitialization.isDestroyed()); +} + +struct Type { + int i; +}; + +Q_GLOBAL_STATIC(Type, checkedAfterInitialization) +void tst_QGlobalStatic::api() +{ + // check the API + QVERIFY((Type *)checkedAfterInitialization); + QVERIFY(checkedAfterInitialization()); + *checkedAfterInitialization = Type(); + *checkedAfterInitialization() = Type(); + + checkedAfterInitialization()->i = 47; + checkedAfterInitialization->i = 42; + QCOMPARE(checkedAfterInitialization()->i, 42); + checkedAfterInitialization()->i = 47; + QCOMPARE(checkedAfterInitialization->i, 47); + + QVERIFY(checkedAfterInitialization.exists()); + QVERIFY(!checkedAfterInitialization.isDestroyed()); +} + +void tst_QGlobalStatic::constVolatile() +{ + QCOMPARE(*constInt(), 42); + QCOMPARE((int)*volatileInt(), -47); + QCOMPARE(*constInt(), 42); + QCOMPARE((int)*volatileInt(), -47); +} + +struct ThrowingType +{ + static QBasicAtomicInt constructedCount; + static QBasicAtomicInt destructedCount; + ThrowingType() + { + throw 0; + } + + ThrowingType(QBasicAtomicInt &throwControl) + { + constructedCount.ref(); + if (throwControl.fetchAndAddRelaxed(-1) != 0) + throw 0; + } + ~ThrowingType() { destructedCount.ref(); } +}; + +QBasicAtomicInt ThrowingType::constructedCount = Q_BASIC_ATOMIC_INITIALIZER(0); +QBasicAtomicInt ThrowingType::destructedCount = Q_BASIC_ATOMIC_INITIALIZER(0); + +Q_GLOBAL_STATIC(ThrowingType, throwingGS) +void tst_QGlobalStatic::exception() +{ + bool exceptionCaught = false; + try { + throwingGS(); + } catch (int) { + exceptionCaught = true; + } + QVERIFY(exceptionCaught); + QCOMPARE(Q_QGS_throwingGS::guard.load(), 0); + QVERIFY(!throwingGS.exists()); + QVERIFY(!throwingGS.isDestroyed()); +} + +QBasicAtomicInt exceptionControlVar = Q_BASIC_ATOMIC_INITIALIZER(1); +Q_GLOBAL_STATIC_WITH_ARGS(ThrowingType, exceptionGS, (exceptionControlVar)) +void tst_QGlobalStatic::threadedException() +{ + if (exceptionControlVar.load() != 1) + QSKIP("This test cannot be run more than once"); + ThrowingType::constructedCount.store(0); + ThrowingType::destructedCount.store(0); + + bool exceptionCaught = false; + try { + exceptionGS(); + } catch (int) { + exceptionCaught = true; + } + QCOMPARE(ThrowingType::constructedCount.load(), 1); + QVERIFY(exceptionCaught); + + exceptionGS(); + QCOMPARE(ThrowingType::constructedCount.load(), 2); +} + +QBasicAtomicInt threadStressTestControlVar = Q_BASIC_ATOMIC_INITIALIZER(5); +Q_GLOBAL_STATIC_WITH_ARGS(ThrowingType, threadStressTestGS, (threadStressTestControlVar)) + + +void tst_QGlobalStatic::threadStressTest() +{ + class ThreadStressTestThread: public QThread + { + public: + QReadWriteLock *lock; + void run() + { + QReadLocker l(lock); + //usleep(qrand() * 200 / RAND_MAX); + // thundering herd + try { + threadStressTestGS(); + } catch (int) { + } + } + }; + + ThrowingType::constructedCount.store(0); + ThrowingType::destructedCount.store(0); + int expectedConstructionCount = threadStressTestControlVar.load() + 1; + if (expectedConstructionCount <= 0) + QSKIP("This test cannot be run more than once"); + + const int numThreads = 200; + ThreadStressTestThread threads[numThreads]; + QReadWriteLock lock; + lock.lockForWrite(); + for (int i = 0; i < numThreads; ++i) { + threads[i].lock = &lock; + threads[i].start(); + } + + // wait for all threads + // release the herd + lock.unlock(); + + for (int i = 0; i < numThreads; ++i) + threads[i].wait(); + + QCOMPARE(ThrowingType::constructedCount.loadAcquire(), expectedConstructionCount); + QCOMPARE(ThrowingType::destructedCount.loadAcquire(), 0); +} + +Q_GLOBAL_STATIC(int, checkedAfterDestruction) +void tst_QGlobalStatic::afterDestruction() +{ + // this test will not produce results now + // it will simply run some code on destruction (after the global statics have been deleted) + // if that fails, this will cause a crash + + // static destruction is LIFO: so we must add our exit-time code before the + // global static is used for the first time + static struct RunAtExit { + ~RunAtExit() { + int *ptr = checkedAfterDestruction(); + if (ptr) + qFatal("Global static is not null as was expected"); + } + } runAtExit; + (void) runAtExit; + + *checkedAfterDestruction = 42; +} + +QTEST_APPLESS_MAIN(tst_QGlobalStatic); + +#include "tst_qglobalstatic.moc" diff --git a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp index fc96d656a0..6f07538c8d 100644 --- a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp +++ b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp @@ -64,6 +64,7 @@ private slots: #endif void qMessagePattern(); + void qMessagePatternIf(); private: QString m_appDir; @@ -702,5 +703,68 @@ void tst_qmessagehandler::qMessagePattern() QCOMPARE(QString::fromLatin1(output), QString::fromLatin1(expected)); } +void tst_qmessagehandler::qMessagePatternIf() +{ + QProcess process; + const QString appExe = m_appDir + "/app"; + + QStringList environment = QProcess::systemEnvironment(); + environment.prepend("QT_MESSAGE_PATTERN=\"[%{if-debug}D%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{message}\""); + process.setEnvironment(environment); + process.start(appExe); + QVERIFY2(process.waitForStarted(), qPrintable( + QString::fromLatin1("Could not start %1: %2").arg(appExe, process.errorString()))); + process.waitForFinished(); + + QByteArray output = process.readAllStandardError(); + // qDebug() << output; + QVERIFY(!output.isEmpty()); + QVERIFY(!output.contains("QT_MESSAGE_PATTERN")); + + QVERIFY(output.contains("[D] static constructor")); + // we can't be sure whether the QT_MESSAGE_PATTERN is already destructed + QVERIFY(output.contains("static destructor")); + QVERIFY(output.contains("[D] qDebug")); + QVERIFY(output.contains("[W] qWarning")); + QVERIFY(output.contains("[C] qCritical")); + QVERIFY(output.contains("[D] qDebug2")); + + // + // Tests some errors + // + environment = QProcess::systemEnvironment(); + environment.prepend("QT_MESSAGE_PATTERN=\"PREFIX: %{unknown} %{endif} %{if-warning}\""); + process.setEnvironment(environment); + + process.start(appExe); + QVERIFY2(process.waitForStarted(), qPrintable( + QString::fromLatin1("Could not start %1: %2").arg(appExe, process.errorString()))); + process.waitForFinished(); + + output = process.readAllStandardError(); + // qDebug() << output; + QVERIFY(!output.isEmpty()); + QVERIFY(output.contains("QT_MESSAGE_PATTERN: Unknown placeholder %{unknown}")); + QVERIFY(output.contains("QT_MESSAGE_PATTERN: %{endif} without an %{if-*}")); + QVERIFY(output.contains("QT_MESSAGE_PATTERN: missing %{endif}")); + + + environment = QProcess::systemEnvironment(); + environment.prepend("QT_MESSAGE_PATTERN=\"A %{if-debug}DEBUG%{if-warning}WARNING%{endif} %{message} \""); + process.setEnvironment(environment); + + process.start(appExe); + QVERIFY2(process.waitForStarted(), qPrintable( + QString::fromLatin1("Could not start %1: %2").arg(appExe, process.errorString()))); + process.waitForFinished(); + + output = process.readAllStandardError(); + // qDebug() << output; + QVERIFY(!output.isEmpty()); + QVERIFY(output.contains("QT_MESSAGE_PATTERN: %{if-*} cannot be nested")); + QVERIFY(output.contains("A DEBUG qDebug")); + QVERIFY(output.contains("A qWarning")); +} + QTEST_MAIN(tst_qmessagehandler) #include "tst_qlogging.moc" diff --git a/tests/auto/corelib/io/io.pro b/tests/auto/corelib/io/io.pro index 03b42a2cbb..b3a51c6f6e 100644 --- a/tests/auto/corelib/io/io.pro +++ b/tests/auto/corelib/io/io.pro @@ -14,12 +14,14 @@ SUBDIRS=\ qfilesystemwatcher \ qiodevice \ qipaddress \ + qlockfile \ qnodebug \ qprocess \ qprocess-noapplication \ qprocessenvironment \ qresourceengine \ qsettings \ + qsavefile \ qstandardpaths \ qtemporarydir \ qtemporaryfile \ @@ -34,6 +36,12 @@ SUBDIRS=\ qwinoverlappedionotifier } +!qtHaveModule(network): SUBDIRS -= \ + qfile \ + qiodevice \ + qprocess \ + qtextstream + !contains(QT_CONFIG, private_tests): SUBDIRS -= \ qabstractfileengine \ qfileinfo \ diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp index 333ccc8e49..f452efc1b3 100644 --- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp +++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp @@ -52,7 +52,8 @@ private slots: void warningWithoutDebug() const; void criticalWithoutDebug() const; void debugWithBool() const; - void debugNoSpaces() const; + void debugSpaceHandling() const; + void stateSaver() const; void veryLongWarningMessage() const; void qDebugQStringRef() const; void qDebugQLatin1String() const; @@ -150,7 +151,36 @@ void tst_QDebug::debugWithBool() const QCOMPARE(QString::fromLatin1(s_function), function); } -void tst_QDebug::debugNoSpaces() const +class MyPoint +{ +public: + MyPoint(int val1, int val2) + : v1(val1), v2(val2) {} + int v1; + int v2; +}; +QDebug operator<< (QDebug s, const MyPoint& point) +{ + const QDebugStateSaver saver(s); + return s.nospace() << "MyPoint(" << point.v1 << ", " << point.v2 << ")"; +} + +class MyLine +{ +public: + MyLine(const MyPoint& point1, const MyPoint& point2) + : p1(point1), p2(point2) {} + MyPoint p1; + MyPoint p2; +}; +QDebug operator<< (QDebug s, const MyLine& line) +{ + const QDebugStateSaver saver(s); + s.nospace() << "MyLine(" << line.p1 << ", " << line.p2 << ")"; + return s; +} + +void tst_QDebug::debugSpaceHandling() const { MessageHandlerSetter mhs(myMessageHandler); { @@ -166,8 +196,26 @@ void tst_QDebug::debugNoSpaces() const d << "key=" << "value"; d.space(); d << 1 << 2; + MyLine line(MyPoint(10, 11), MyPoint (12, 13)); + d << line; + // With the old implementation of MyPoint doing dbg.nospace() << ...; dbg.space() we ended up with + // MyLine(MyPoint(10, 11) , MyPoint(12, 13) ) + } + QCOMPARE(s_msg, QString::fromLatin1(" foo key=value 1 2 MyLine(MyPoint(10, 11), MyPoint(12, 13))")); +} + +void tst_QDebug::stateSaver() const +{ + MessageHandlerSetter mhs(myMessageHandler); + { + QDebug d = qDebug(); + { + QDebugStateSaver saver(d); + d.nospace() << hex << right << qSetFieldWidth(3) << qSetPadChar('0') << 42; + } + d.space() << 42; } - QCOMPARE(s_msg, QString::fromLatin1(" foo key=value 1 2 ")); + QCOMPARE(s_msg, QString::fromLatin1("02a 42 ")); } void tst_QDebug::veryLongWarningMessage() const diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp index 6fa222dd72..c0afb83cb1 100644 --- a/tests/auto/corelib/io/qfile/tst_qfile.cpp +++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp @@ -80,6 +80,12 @@ QT_END_NAMESPACE # include <sys/statfs.h> #elif defined(Q_OS_WINCE) # include <qplatformdefs.h> +#elif defined(Q_OS_VXWORKS) +# include <fcntl.h> +#if defined(_WRS_KERNEL) +#undef QT_OPEN +#define QT_OPEN(path, oflag) ::open(path, oflag, 0) +#endif #endif #ifdef Q_OS_QNX @@ -487,11 +493,6 @@ void tst_QFile::open_data() QTest::addColumn<bool>("ok"); QTest::addColumn<QFile::FileError>("status"); -#ifdef Q_OS_MAC - static const QString denied("Operation not permitted"); -#else - static const QString denied("Permission denied"); -#endif QTest::newRow( "exist_readOnly" ) << m_testFile << int(QIODevice::ReadOnly) << true << QFile::NoError; @@ -551,7 +552,7 @@ void tst_QFile::open() QFETCH( bool, ok ); -#if defined(Q_OS_UNIX) +#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS) if (::getuid() == 0) // root and Chuck Norris don't care for file permissions. Skip. QSKIP("Running this test as root doesn't make sense"); @@ -2248,7 +2249,7 @@ static QByteArray getLargeDataBlock() if (array.isNull()) { -#if defined(Q_OS_WINCE) +#if defined(Q_OS_WINCE) || defined(Q_OS_VXWORKS) int resizeSize = 1024 * 1024; // WinCE does not have much space #else int resizeSize = 64 * 1024 * 1024; @@ -2438,7 +2439,9 @@ void tst_QFile::rename() #if defined(Q_OS_UNIX) if (strcmp(QTest::currentDataTag(), "renamefile -> /etc/renamefile") == 0) { +#if !defined(Q_OS_VXWORKS) if (::getuid() == 0) +#endif QSKIP("Running this test as root doesn't make sense"); } #endif @@ -2947,6 +2950,7 @@ void tst_QFile::map() file.close(); +#if !defined(Q_OS_VXWORKS) #if defined(Q_OS_UNIX) if (::getuid() != 0) // root always has permissions @@ -2961,6 +2965,7 @@ void tst_QFile::map() QVERIFY(!memory); QVERIFY(file.setPermissions(originalPermissions)); } +#endif QVERIFY(file.remove()); } diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp index ded77c649f..bcc971bf4b 100644 --- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp @@ -46,6 +46,7 @@ #include <qcoreapplication.h> #include <qlibrary.h> #include <qtemporaryfile.h> +#include <qtemporarydir.h> #include <qdir.h> #include <qfileinfo.h> #ifdef Q_OS_UNIX @@ -54,10 +55,11 @@ #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> +#ifndef Q_OS_VXWORKS #include <pwd.h> #endif +#endif #ifdef Q_OS_WIN -#define _WIN32_WINNT 0x500 #include <qt_windows.h> #include <qlibrary.h> #if !defined(Q_OS_WINCE) @@ -72,6 +74,10 @@ #include <private/qfileinfo_p.h> #include "../../../../shared/filesystem.h" +#if defined(Q_OS_VXWORKS) +#define Q_NO_SYMLINKS +#endif + QT_BEGIN_NAMESPACE extern Q_AUTOTEST_EXPORT bool qIsLikelyToBeNfs(int /* handle */); QT_END_NAMESPACE @@ -80,7 +86,11 @@ class tst_QFileInfo : public QObject { Q_OBJECT +public: + tst_QFileInfo() : m_currentDir(QDir::currentPath()) {} + private slots: + void initTestCase(); void cleanupTestCase(); void getSetCheck(); @@ -190,32 +200,27 @@ private slots: void invalidState(); void nonExistingFileDates(); + +private: + const QString m_currentDir; + QString m_sourceFile; + QString m_resourcesDir; + QTemporaryDir m_dir; }; -void tst_QFileInfo::cleanupTestCase() +void tst_QFileInfo::initTestCase() { - QFile::remove("brokenlink.lnk"); - QFile::remove("link.lnk"); - QFile::remove("file1"); - QFile::remove("dummyfile"); - QFile::remove("simplefile.txt"); - QFile::remove("longFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileName.txt"); - QFile::remove("tempfile.txt"); + m_sourceFile = QFINDTESTDATA("tst_qfileinfo.cpp"); + QVERIFY(!m_sourceFile.isEmpty()); + m_resourcesDir = QFINDTESTDATA("resources"); + QVERIFY(!m_resourcesDir.isEmpty()); + QVERIFY(m_dir.isValid()); + QVERIFY(QDir::setCurrent(m_dir.path())); +} -#if defined(Q_OS_UNIX) - QDir().rmdir("./.hidden-directory"); - QFile::remove("link_to_tst_qfileinfo"); -#endif -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) - QDir().rmdir("./hidden-directory"); - QDir().rmdir("abs_symlink"); - QDir().rmdir("rel_symlink"); - QDir().rmdir("junction_pwd"); - QDir().rmdir("junction_root"); - QDir().rmdir("mountpoint"); - QFile::remove("abs_symlink.cpp"); - QFile::remove("rel_symlink.cpp"); -#endif +void tst_QFileInfo::cleanupTestCase() +{ + QDir::setCurrent(m_currentDir); // Release temporary directory so that it can be deleted on Windows } // Testing get/set functions @@ -237,10 +242,9 @@ static QFileInfoPrivate* getPrivate(QFileInfo &info) void tst_QFileInfo::copy() { - QTemporaryFile *t; - t = new QTemporaryFile; - t->open(); - QFileInfo info(t->fileName()); + QTemporaryFile t; + t.open(); + QFileInfo info(t.fileName()); QVERIFY(info.exists()); //copy constructor @@ -287,7 +291,7 @@ void tst_QFileInfo::isFile_data() QTest::addColumn<bool>("expected"); QTest::newRow("data0") << QDir::currentPath() << false; - QTest::newRow("data1") << QFINDTESTDATA("tst_qfileinfo.cpp") << true; + QTest::newRow("data1") << m_sourceFile << true; QTest::newRow("data2") << ":/tst_qfileinfo/resources/" << false; QTest::newRow("data3") << ":/tst_qfileinfo/resources/file1" << true; QTest::newRow("data4") << ":/tst_qfileinfo/resources/afilethatshouldnotexist" << false; @@ -320,13 +324,13 @@ void tst_QFileInfo::isDir_data() QTest::addColumn<bool>("expected"); QTest::newRow("data0") << QDir::currentPath() << true; - QTest::newRow("data1") << QFINDTESTDATA("tst_qfileinfo.cpp") << false; + QTest::newRow("data1") << m_sourceFile << false; QTest::newRow("data2") << ":/tst_qfileinfo/resources/" << true; QTest::newRow("data3") << ":/tst_qfileinfo/resources/file1" << false; QTest::newRow("data4") << ":/tst_qfileinfo/resources/afilethatshouldnotexist" << false; - QTest::newRow("simple dir") << QFINDTESTDATA("resources") << true; - QTest::newRow("simple dir with slash") << QFINDTESTDATA("resources/") << true; + QTest::newRow("simple dir") << m_resourcesDir << true; + QTest::newRow("simple dir with slash") << (m_resourcesDir + QLatin1Char('/')) << true; QTest::newRow("broken link") << "brokenlink.lnk" << false; @@ -366,8 +370,8 @@ void tst_QFileInfo::isRoot_data() QTest::newRow("data4") << ":/tst_qfileinfo/resources/" << false; QTest::newRow("data5") << ":/" << true; - QTest::newRow("simple dir") << QFINDTESTDATA("resources") << false; - QTest::newRow("simple dir with slash") << QFINDTESTDATA("resources/") << false; + QTest::newRow("simple dir") << m_resourcesDir << false; + QTest::newRow("simple dir with slash") << (m_resourcesDir + QLatin1Char('/')) << false; #if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) QTest::newRow("drive 1") << "c:" << false; QTest::newRow("drive 2") << "c:/" << true; @@ -398,21 +402,21 @@ void tst_QFileInfo::exists_data() QTest::addColumn<bool>("expected"); QTest::newRow("data0") << QDir::currentPath() << true; - QTest::newRow("data1") << QFINDTESTDATA("tst_qfileinfo.cpp") << true; + QTest::newRow("data1") << m_sourceFile << true; QTest::newRow("data2") << "/I/do_not_expect_this_path_to_exist/" << false; QTest::newRow("data3") << ":/tst_qfileinfo/resources/" << true; QTest::newRow("data4") << ":/tst_qfileinfo/resources/file1" << true; QTest::newRow("data5") << ":/I/do_not_expect_this_path_to_exist/" << false; - QTest::newRow("data6") << (QFINDTESTDATA("resources/") + "*") << false; - QTest::newRow("data7") << (QFINDTESTDATA("resources/") + "*.foo") << false; - QTest::newRow("data8") << (QFINDTESTDATA("resources/") + "*.ext1") << false; - QTest::newRow("data9") << (QFINDTESTDATA("resources/") + "file?.ext1") << false; + QTest::newRow("data6") << (m_resourcesDir + "/*") << false; + QTest::newRow("data7") << (m_resourcesDir + "/*.foo") << false; + QTest::newRow("data8") << (m_resourcesDir + "/*.ext1") << false; + QTest::newRow("data9") << (m_resourcesDir + "/file?.ext1") << false; QTest::newRow("data10") << "." << true; QTest::newRow("data11") << ". " << false; QTest::newRow("empty") << "" << false; - QTest::newRow("simple dir") << QFINDTESTDATA("resources") << true; - QTest::newRow("simple dir with slash") << QFINDTESTDATA("resources/") << true; + QTest::newRow("simple dir") << m_resourcesDir << true; + QTest::newRow("simple dir with slash") << (m_resourcesDir + QLatin1Char('/')) << true; #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) QTest::newRow("unc 1") << "//" + QtNetworkSettings::winServerName() << true; @@ -561,7 +565,7 @@ void tst_QFileInfo::canonicalFilePath() // test symlinks QFile::remove("link.lnk"); { - QFile file(QFINDTESTDATA("tst_qfileinfo.cpp")); + QFile file(m_sourceFile); if (file.link("link.lnk")) { QFileInfo info1(file); QFileInfo info2("link.lnk"); @@ -587,7 +591,7 @@ void tst_QFileInfo::canonicalFilePath() QCOMPARE(info1.canonicalFilePath(), info2.canonicalFilePath()); QFileInfo info3(link + QDir::separator() + "link.lnk"); - QFileInfo info4(QFINDTESTDATA("tst_qfileinfo.cpp")); + QFileInfo info4(m_sourceFile); QVERIFY(!info3.canonicalFilePath().isEmpty()); QCOMPARE(info4.canonicalFilePath(), info3.canonicalFilePath()); @@ -621,20 +625,21 @@ void tst_QFileInfo::canonicalFilePath() // CreateSymbolicLink can return TRUE & still fail to create the link, // the error code in that case is ERROR_PRIVILEGE_NOT_HELD (1314) SetLastError(0); - BOOL ret = ptrCreateSymbolicLink((wchar_t*)QString("res").utf16(), (wchar_t*)QString("resources").utf16(), 1); + const QString linkTarget = QStringLiteral("res"); + BOOL ret = ptrCreateSymbolicLink((wchar_t*)linkTarget.utf16(), (wchar_t*)m_resourcesDir.utf16(), 1); DWORD dwErr = GetLastError(); if (!ret) QSKIP("Symbolic links aren't supported by FS"); QString currentPath = QDir::currentPath(); - bool is_res_Current = QDir::setCurrent("res"); + bool is_res_Current = QDir::setCurrent(linkTarget); if (!is_res_Current && dwErr == 1314) QSKIP("Not enough privilages to create Symbolic links"); QCOMPARE(is_res_Current, true); + const QString actualCanonicalPath = QFileInfo("file1").canonicalFilePath(); + QVERIFY(QDir::setCurrent(currentPath)); + QCOMPARE(actualCanonicalPath, m_resourcesDir + QStringLiteral("/file1")); - QCOMPARE(QFileInfo("file1").canonicalFilePath(), currentPath + "/resources/file1"); - - QCOMPARE(QDir::setCurrent(currentPath), true); - QDir::current().rmdir("res"); + QDir::current().rmdir(linkTarget); } #endif } @@ -855,7 +860,7 @@ void tst_QFileInfo::permission_data() QTest::addColumn<bool>("expected"); QTest::newRow("data0") << QCoreApplication::instance()->applicationFilePath() << int(QFile::ExeUser) << true; - QTest::newRow("data1") << QFINDTESTDATA("tst_qfileinfo.cpp") << int(QFile::ReadUser) << true; + QTest::newRow("data1") << m_sourceFile << int(QFile::ReadUser) << true; QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << int(QFile::ReadUser) << true; QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1" << int(QFile::WriteUser) << false; QTest::newRow("resource3") << ":/tst_qfileinfo/resources/file1.ext1" << int(QFile::ExeUser) << false; @@ -921,13 +926,15 @@ void tst_QFileInfo::compare_data() if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) caseSensitiveOnMac = false; #endif + QString caseChangedSource = m_sourceFile; + caseChangedSource.replace("info", "Info"); QTest::newRow("data0") - << QFINDTESTDATA("tst_qfileinfo.cpp") - << QFINDTESTDATA("tst_qfileinfo.cpp") + << m_sourceFile + << m_sourceFile << true; QTest::newRow("data1") - << QFINDTESTDATA("tst_qfileinfo.cpp") + << m_sourceFile << QString::fromLatin1("/tst_qfileinfo.cpp") << false; QTest::newRow("data2") @@ -935,8 +942,8 @@ void tst_QFileInfo::compare_data() << QDir::currentPath() + QString::fromLatin1("/tst_qfileinfo.cpp") << true; QTest::newRow("casesense1") - << QFINDTESTDATA("tst_qfileinfo.cpp").replace("info", "Info") - << QFINDTESTDATA("tst_qfileinfo.cpp") + << caseChangedSource + << m_sourceFile #if defined(Q_OS_WIN) << true; #elif defined(Q_OS_MAC) @@ -1013,7 +1020,7 @@ void tst_QFileInfo::fileTimes() QEXPECT_FAIL("longfile absolutepath", "No long filenames on WinCE", Abort); #endif QVERIFY(file.open(QFile::WriteOnly | QFile::Text)); -#ifdef Q_OS_UNIX +#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS) if (qIsLikelyToBeNfs(file.handle())) QSKIP("This Test doesn't work on NFS"); #endif @@ -1140,7 +1147,7 @@ void tst_QFileInfo::isSymLink_data() QFile::remove("brokenlink.lnk"); QFile::remove("dummyfile"); - QFile file1(QFINDTESTDATA("tst_qfileinfo.cpp")); + QFile file1(m_sourceFile); QVERIFY(file1.link("link.lnk")); QFile file2("dummyfile"); @@ -1152,8 +1159,8 @@ void tst_QFileInfo::isSymLink_data() QTest::addColumn<bool>("isSymLink"); QTest::addColumn<QString>("linkTarget"); - QTest::newRow("existent file") << QFINDTESTDATA("tst_qfileinfo.cpp") << false << ""; - QTest::newRow("link") << "link.lnk" << true << QFileInfo(QFINDTESTDATA("tst_qfileinfo.cpp")).absoluteFilePath(); + QTest::newRow("existent file") << m_sourceFile << false << ""; + QTest::newRow("link") << "link.lnk" << true << QFileInfo(m_sourceFile).absoluteFilePath(); QTest::newRow("broken link") << "brokenlink.lnk" << true << QFileInfo("dummyfile").absoluteFilePath(); } @@ -1390,7 +1397,7 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data() } { //File symlinks - QFileInfo target(QFINDTESTDATA("tst_qfileinfo.cpp")); + QFileInfo target(m_sourceFile); QString absTarget = QDir::toNativeSeparators(target.absoluteFilePath()); QString absSymlink = QDir::toNativeSeparators(pwd.absolutePath()).append("\\abs_symlink.cpp"); QString relTarget = QDir::toNativeSeparators(pwd.relativeFilePath(target.absoluteFilePath())); @@ -1447,10 +1454,22 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks() QFETCH(QString, canonicalFilePath); QFileInfo fi(path); - QCOMPARE(fi.isSymLink(), isSymLink); + const bool actualIsSymLink = fi.isSymLink(); + const QString actualSymLinkTarget = isSymLink ? fi.symLinkTarget() : QString(); + const QString actualCanonicalFilePath = isSymLink ? fi.canonicalFilePath() : QString(); + // Ensure that junctions, mountpoints are removed. If this fails, do not remove + // temporary directory to prevent it from trashing the system. + if (fi.isDir()) { + if (!QDir().rmdir(fi.fileName())) { + qWarning("Unable to remove NTFS junction '%s'', keeping '%s'.", + qPrintable(fi.fileName()), qPrintable(QDir::toNativeSeparators(m_dir.path()))); + m_dir.setAutoRemove(false); + } + } + QCOMPARE(actualIsSymLink, isSymLink); if (isSymLink) { - QCOMPARE(fi.symLinkTarget(), linkTarget); - QCOMPARE(fi.canonicalFilePath(), canonicalFilePath); + QCOMPARE(actualSymLinkTarget, linkTarget); + QCOMPARE(actualCanonicalFilePath, canonicalFilePath); } } @@ -1499,7 +1518,7 @@ void tst_QFileInfo::isWritable() #if defined (Q_OS_BLACKBERRY) // The Blackberry filesystem is read-only QVERIFY(!QFileInfo("/etc/passwd").isWritable()); -#elif defined (Q_OS_UNIX) +#elif defined (Q_OS_UNIX) && !defined(Q_OS_VXWORKS) // VxWorks does not have users/groups if (::getuid() == 0) QVERIFY(QFileInfo("/etc/passwd").isWritable()); else @@ -1698,7 +1717,7 @@ QT_END_NAMESPACE void tst_QFileInfo::owner() { QString userName; -#if defined(Q_OS_UNIX) +#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS) { passwd *user = getpwuid(geteuid()); QVERIFY(user); @@ -1761,7 +1780,7 @@ void tst_QFileInfo::owner() void tst_QFileInfo::group() { QString expected; -#if defined(Q_OS_UNIX) +#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS) struct group *gr; gid_t gid = getegid(); diff --git a/tests/auto/corelib/io/qlockfile/qlockfile.pro b/tests/auto/corelib/io/qlockfile/qlockfile.pro new file mode 100644 index 0000000000..91f104305c --- /dev/null +++ b/tests/auto/corelib/io/qlockfile/qlockfile.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs + +SUBDIRS += tst_qlockfile.pro qlockfiletesthelper/qlockfile_test_helper.pro diff --git a/tests/auto/corelib/io/qlockfile/qlockfiletesthelper/qlockfile_test_helper.cpp b/tests/auto/corelib/io/qlockfile/qlockfiletesthelper/qlockfile_test_helper.cpp new file mode 100644 index 0000000000..63f6291034 --- /dev/null +++ b/tests/auto/corelib/io/qlockfile/qlockfiletesthelper/qlockfile_test_helper.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QDebug> +#include <QCoreApplication> +#include <QLockFile> +#include <QThread> + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + + if (argc <= 1) + return -1; + + const QString lockName = QString::fromLocal8Bit(argv[1]); + + QString option; + if (argc > 2) + option = QString::fromLocal8Bit(argv[2]); + + if (option == "-crash") { + QLockFile *lockFile = new QLockFile(lockName); + lockFile->lock(); + // leak the lockFile on purpose, so that the lock remains! + return 0; + } else if (option == "-busy") { + QLockFile lockFile(lockName); + lockFile.lock(); + QThread::msleep(500); + return 0; + } else { + QLockFile lockFile(lockName); + if (lockFile.isLocked()) // cannot happen, before calling lock or tryLock + return QLockFile::UnknownError; + + lockFile.tryLock(); + return lockFile.error(); + } +} diff --git a/tests/auto/corelib/io/qlockfile/qlockfiletesthelper/qlockfile_test_helper.pro b/tests/auto/corelib/io/qlockfile/qlockfiletesthelper/qlockfile_test_helper.pro new file mode 100644 index 0000000000..3ac3be9c9b --- /dev/null +++ b/tests/auto/corelib/io/qlockfile/qlockfiletesthelper/qlockfile_test_helper.pro @@ -0,0 +1,7 @@ +TARGET = qlockfile_test_helper +SOURCES += qlockfile_test_helper.cpp + +CONFIG += console +CONFIG -= app_bundle +QT = core +DESTDIR = ./ diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp new file mode 100644 index 0000000000..4aed11a2aa --- /dev/null +++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp @@ -0,0 +1,379 @@ +/**************************************************************************** +** +** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> +#include <QtConcurrentRun> +#include <qlockfile.h> +#include <qtemporarydir.h> + +class tst_QLockFile : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + void lockUnlock(); + void lockOutOtherProcess(); + void lockOutOtherThread(); + void waitForLock_data(); + void waitForLock(); + void staleLockFromCrashedProcess_data(); + void staleLockFromCrashedProcess(); + void staleShortLockFromBusyProcess(); + void staleLongLockFromBusyProcess(); + void staleLockRace(); + void noPermissions(); + +public: + QString m_helperApp; + QTemporaryDir dir; +}; + +void tst_QLockFile::initTestCase() +{ +#ifdef QT_NO_PROCESS + QSKIP("This test requires QProcess support"); +#else + // chdir to our testdata path and execute helper apps relative to that. + QString testdata_dir = QFileInfo(QFINDTESTDATA("qlockfiletesthelper")).absolutePath(); + QVERIFY2(QDir::setCurrent(testdata_dir), qPrintable("Could not chdir to " + testdata_dir)); + m_helperApp = "qlockfiletesthelper/qlockfile_test_helper"; +#endif +} + +void tst_QLockFile::lockUnlock() +{ + const QString fileName = dir.path() + "/lock1"; + QVERIFY(!QFile(fileName).exists()); + QLockFile lockFile(fileName); + QVERIFY(lockFile.lock()); + QVERIFY(lockFile.isLocked()); + QCOMPARE(int(lockFile.error()), int(QLockFile::NoError)); + QVERIFY(QFile::exists(fileName)); + + // Recursive locking is not allowed + // (can't test lock() here, it would wait forever) + QVERIFY(!lockFile.tryLock()); + QCOMPARE(int(lockFile.error()), int(QLockFile::LockFailedError)); + qint64 pid; + QString hostname, appname; + QVERIFY(lockFile.getLockInfo(&pid, &hostname, &appname)); + QCOMPARE(pid, QCoreApplication::applicationPid()); + QCOMPARE(appname, qAppName()); + QVERIFY(!lockFile.tryLock(200)); + QCOMPARE(int(lockFile.error()), int(QLockFile::LockFailedError)); + + // Unlock deletes the lock file + lockFile.unlock(); + QCOMPARE(int(lockFile.error()), int(QLockFile::NoError)); + QVERIFY(!lockFile.isLocked()); + QVERIFY(!QFile::exists(fileName)); +} + +void tst_QLockFile::lockOutOtherProcess() +{ + // Lock + const QString fileName = dir.path() + "/lockOtherProcess"; + QLockFile lockFile(fileName); + QVERIFY(lockFile.lock()); + + // Other process can't acquire lock + QProcess proc; + proc.start(m_helperApp, QStringList() << fileName); + QVERIFY2(proc.waitForStarted(), qPrintable(proc.errorString())); + QVERIFY(proc.waitForFinished()); + QCOMPARE(proc.exitCode(), int(QLockFile::LockFailedError)); + + // Unlock + lockFile.unlock(); + QVERIFY(!QFile::exists(fileName)); + + // Other process can now acquire lock + int ret = QProcess::execute(m_helperApp, QStringList() << fileName); + QCOMPARE(ret, int(QLockFile::NoError)); + // Lock doesn't survive process though (on clean exit) + QVERIFY(!QFile::exists(fileName)); +} + +static QLockFile::LockError tryLockFromThread(const QString &fileName) +{ + QLockFile lockInThread(fileName); + lockInThread.tryLock(); + return lockInThread.error(); +} + +void tst_QLockFile::lockOutOtherThread() +{ + const QString fileName = dir.path() + "/lockOtherThread"; + QLockFile lockFile(fileName); + QVERIFY(lockFile.lock()); + + // Other thread can't acquire lock + QFuture<QLockFile::LockError> ret = QtConcurrent::run<QLockFile::LockError>(tryLockFromThread, fileName); + QCOMPARE(ret.result(), QLockFile::LockFailedError); + + lockFile.unlock(); + + // Now other thread can acquire lock + QFuture<QLockFile::LockError> ret2 = QtConcurrent::run<QLockFile::LockError>(tryLockFromThread, fileName); + QCOMPARE(ret2.result(), QLockFile::NoError); +} + +static bool lockFromThread(const QString &fileName, int sleepMs, QSemaphore *semThreadReady, QSemaphore *semMainThreadDone) +{ + QLockFile lockFile(fileName); + if (!lockFile.lock()) { + qWarning() << "Locking failed" << lockFile.error(); + return false; + } + semThreadReady->release(); + QThread::msleep(sleepMs); + semMainThreadDone->acquire(); + lockFile.unlock(); + return true; +} + +void tst_QLockFile::waitForLock_data() +{ + QTest::addColumn<int>("testNumber"); + QTest::addColumn<int>("threadSleepMs"); + QTest::addColumn<bool>("releaseEarly"); + QTest::addColumn<int>("tryLockTimeout"); + QTest::addColumn<bool>("expectedResult"); + + int tn = 0; // test number + QTest::newRow("wait_forever_succeeds") << ++tn << 500 << true << -1 << true; + QTest::newRow("wait_longer_succeeds") << ++tn << 500 << true << 1000 << true; + QTest::newRow("wait_zero_fails") << ++tn << 500 << false << 0 << false; + QTest::newRow("wait_not_enough_fails") << ++tn << 500 << false << 100 << false; +} + +void tst_QLockFile::waitForLock() +{ + QFETCH(int, testNumber); + QFETCH(int, threadSleepMs); + QFETCH(bool, releaseEarly); + QFETCH(int, tryLockTimeout); + QFETCH(bool, expectedResult); + + const QString fileName = dir.path() + "/waitForLock" + QString::number(testNumber); + QLockFile lockFile(fileName); + QSemaphore semThreadReady, semMainThreadDone; + // Lock file from a thread + QFuture<bool> ret = QtConcurrent::run<bool>(lockFromThread, fileName, threadSleepMs, &semThreadReady, &semMainThreadDone); + semThreadReady.acquire(); + + if (releaseEarly) // let the thread release the lock after threadSleepMs + semMainThreadDone.release(); + + QCOMPARE(lockFile.tryLock(tryLockTimeout), expectedResult); + if (expectedResult) + QCOMPARE(int(lockFile.error()), int(QLockFile::NoError)); + else + QCOMPARE(int(lockFile.error()), int(QLockFile::LockFailedError)); + + if (!releaseEarly) // only let the thread release the lock now + semMainThreadDone.release(); + + QVERIFY(ret); // waits for the thread to finish +} + +void tst_QLockFile::staleLockFromCrashedProcess_data() +{ + QTest::addColumn<int>("staleLockTime"); + + // Test both use cases for QLockFile, should make no difference here. + QTest::newRow("short") << 30000; + QTest::newRow("long") << 0; +} + +void tst_QLockFile::staleLockFromCrashedProcess() +{ + QFETCH(int, staleLockTime); + const QString fileName = dir.path() + "/staleLockFromCrashedProcess"; + + int ret = QProcess::execute(m_helperApp, QStringList() << fileName << "-crash"); + QCOMPARE(ret, int(QLockFile::NoError)); + QTRY_VERIFY(QFile::exists(fileName)); + + QLockFile secondLock(fileName); + secondLock.setStaleLockTime(staleLockTime); + // tryLock detects and removes the stale lock (since the PID is dead) +#ifdef Q_OS_WIN + // It can take a bit of time on Windows, though. + QVERIFY(secondLock.tryLock(2000)); +#else + QVERIFY(secondLock.tryLock()); +#endif + QCOMPARE(int(secondLock.error()), int(QLockFile::NoError)); +} + +void tst_QLockFile::staleShortLockFromBusyProcess() +{ + const QString fileName = dir.path() + "/staleLockFromBusyProcess"; + + QProcess proc; + proc.start(m_helperApp, QStringList() << fileName << "-busy"); + QVERIFY2(proc.waitForStarted(), qPrintable(proc.errorString())); + QTRY_VERIFY(QFile::exists(fileName)); + + QLockFile secondLock(fileName); + QVERIFY(!secondLock.tryLock()); // held by other process + QCOMPARE(int(secondLock.error()), int(QLockFile::LockFailedError)); + qint64 pid; + QString hostname, appname; + QTRY_VERIFY(secondLock.getLockInfo(&pid, &hostname, &appname)); +#ifdef Q_OS_UNIX + QCOMPARE(pid, proc.pid()); +#endif + + secondLock.setStaleLockTime(100); + QTest::qSleep(100); // make the lock stale + // We can't "steal" (delete+recreate) a lock file from a running process + // until the file descriptor is closed. + QVERIFY(!secondLock.tryLock()); + + proc.waitForFinished(); + QVERIFY(secondLock.tryLock()); +} + +void tst_QLockFile::staleLongLockFromBusyProcess() +{ + const QString fileName = dir.path() + "/staleLockFromBusyProcess"; + + QProcess proc; + proc.start(m_helperApp, QStringList() << fileName << "-busy"); + QVERIFY2(proc.waitForStarted(), qPrintable(proc.errorString())); + QTRY_VERIFY(QFile::exists(fileName)); + + QLockFile secondLock(fileName); + secondLock.setStaleLockTime(0); + QVERIFY(!secondLock.tryLock(100)); // never stale + QCOMPARE(int(secondLock.error()), int(QLockFile::LockFailedError)); + qint64 pid; + QTRY_VERIFY(secondLock.getLockInfo(&pid, NULL, NULL)); + QVERIFY(pid > 0); + + // As long as the other process is running, we can't remove the lock file + QVERIFY(!secondLock.removeStaleLockFile()); + + proc.waitForFinished(); +} + +static QString tryStaleLockFromThread(const QString &fileName) +{ + QLockFile lockInThread(fileName + ".lock"); + lockInThread.setStaleLockTime(1000); + if (!lockInThread.lock()) + return "Error locking: " + QString::number(lockInThread.error()); + + // The concurrent use of the file below (write, read, delete) is protected by the lock file above. + // (provided that it doesn't become stale due to this operation taking too long) + QFile theFile(fileName); + if (!theFile.open(QIODevice::WriteOnly)) + return "Couldn't open for write"; + theFile.write("Hello world"); + theFile.flush(); + theFile.close(); + QFile reader(fileName); + if (!reader.open(QIODevice::ReadOnly)) + return "Couldn't open for read"; + const QByteArray read = reader.readAll(); + if (read != "Hello world") + return "File didn't have the expected contents:" + read; + reader.remove(); + return QString(); +} + +void tst_QLockFile::staleLockRace() +{ + // Multiple threads notice a stale lock at the same time + // Only one thread should delete it, otherwise a race will ensue + const QString fileName = dir.path() + "/sharedFile"; + const QString lockName = fileName + ".lock"; + int ret = QProcess::execute(m_helperApp, QStringList() << lockName << "-crash"); + QCOMPARE(ret, int(QLockFile::NoError)); + QTRY_VERIFY(QFile::exists(lockName)); + + QThreadPool::globalInstance()->setMaxThreadCount(10); + QFutureSynchronizer<QString> synchronizer; + for (int i = 0; i < 8; ++i) + synchronizer.addFuture(QtConcurrent::run<QString>(tryStaleLockFromThread, fileName)); + synchronizer.waitForFinished(); + foreach (const QFuture<QString> &future, synchronizer.futures()) + QVERIFY2(future.result().isEmpty(), qPrintable(future.result())); +} + +void tst_QLockFile::noPermissions() +{ +#ifdef Q_OS_WIN + // A readonly directory still allows us to create files, on Windows. + QSKIP("No permission testing on Windows"); +#endif + // Restore permissions so that the QTemporaryDir cleanup can happen + class PermissionRestorer + { + QString m_path; + public: + PermissionRestorer(const QString& path) + : m_path(path) + {} + + ~PermissionRestorer() + { + QFile file(m_path); + file.setPermissions(QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner)); + } + }; + + const QString fileName = dir.path() + "/staleLock"; + QFile dirAsFile(dir.path()); // I have to use QFile to change a dir's permissions... + QVERIFY2(dirAsFile.setPermissions(QFile::Permissions(0)), qPrintable(dir.path())); // no permissions + PermissionRestorer permissionRestorer(dir.path()); + + QLockFile lockFile(fileName); + QVERIFY(!lockFile.lock()); + QCOMPARE(int(lockFile.error()), int(QLockFile::PermissionError)); +} + +QTEST_MAIN(tst_QLockFile) +#include "tst_qlockfile.moc" diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro b/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro new file mode 100644 index 0000000000..2f7009b736 --- /dev/null +++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro @@ -0,0 +1,6 @@ +CONFIG += testcase +CONFIG -= app_bundle +TARGET = tst_qlockfile +SOURCES += tst_qlockfile.cpp + +QT = core testlib concurrent diff --git a/tests/auto/corelib/io/qprocess/testForwarding/testForwarding.pro b/tests/auto/corelib/io/qprocess/testForwarding/testForwarding.pro index 271c7ead13..45b498c32a 100644 --- a/tests/auto/corelib/io/qprocess/testForwarding/testForwarding.pro +++ b/tests/auto/corelib/io/qprocess/testForwarding/testForwarding.pro @@ -2,3 +2,4 @@ SOURCES = main.cpp CONFIG -= app_bundle CONFIG += console DESTDIR = ./ +QT = core diff --git a/tests/auto/corelib/io/qprocess/testProcessNormal/testProcessNormal.pro b/tests/auto/corelib/io/qprocess/testProcessNormal/testProcessNormal.pro index f7c57abc37..f7bb0985a3 100644 --- a/tests/auto/corelib/io/qprocess/testProcessNormal/testProcessNormal.pro +++ b/tests/auto/corelib/io/qprocess/testProcessNormal/testProcessNormal.pro @@ -4,3 +4,4 @@ CONFIG -= qt app_bundle DESTDIR = ./ DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 +QT = core diff --git a/tests/auto/corelib/io/qprocess/testProcessOutput/testProcessOutput.pro b/tests/auto/corelib/io/qprocess/testProcessOutput/testProcessOutput.pro index 3940ddbf98..2de4534896 100644 --- a/tests/auto/corelib/io/qprocess/testProcessOutput/testProcessOutput.pro +++ b/tests/auto/corelib/io/qprocess/testProcessOutput/testProcessOutput.pro @@ -3,3 +3,4 @@ CONFIG -= qt app_bundle CONFIG += console DESTDIR = ./ DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 +QT = core diff --git a/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/twospaces.pro b/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/twospaces.pro index 43db95e675..8b16f65e34 100644 --- a/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/twospaces.pro +++ b/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/twospaces.pro @@ -6,3 +6,4 @@ OBJECTS_DIR = $${OBJECTS_DIR}-twospaces TARGET = "two space s" DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 +QT = core diff --git a/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/testSetWorkingDirectory.pro b/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/testSetWorkingDirectory.pro index 86d26c2c4a..d425d5569e 100644 --- a/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/testSetWorkingDirectory.pro +++ b/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/testSetWorkingDirectory.pro @@ -3,3 +3,4 @@ CONFIG += console CONFIG -= app_bundle DESTDIR = ./ DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 +QT = core diff --git a/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro b/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro index c5fb286d0c..7f3b8ade3e 100644 --- a/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro +++ b/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro @@ -10,3 +10,4 @@ CONFIG -= qt app_bundle CONFIG += console DESTDIR = ./ DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 +QT = core diff --git a/tests/auto/corelib/io/qprocess/testSpaceInName/testSpaceInName.pro b/tests/auto/corelib/io/qprocess/testSpaceInName/testSpaceInName.pro index d0848e3303..b7213ae507 100644 --- a/tests/auto/corelib/io/qprocess/testSpaceInName/testSpaceInName.pro +++ b/tests/auto/corelib/io/qprocess/testSpaceInName/testSpaceInName.pro @@ -7,3 +7,4 @@ mac { CONFIG -= app_bundle } DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 +QT = core diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index 7965d1d431..11824f4ab6 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -1256,7 +1256,6 @@ void tst_QProcess::waitForBytesWrittenInABytesWrittenSlot() process->start("testProcessEcho/testProcessEcho"); QVERIFY(process->waitForStarted(5000)); - qRegisterMetaType<qint64>("qint64"); QSignalSpy spy(process, SIGNAL(bytesWritten(qint64))); QVERIFY(spy.isValid()); process->write("f"); diff --git a/tests/auto/corelib/io/qsavefile/qsavefile.pro b/tests/auto/corelib/io/qsavefile/qsavefile.pro new file mode 100644 index 0000000000..36db000fa7 --- /dev/null +++ b/tests/auto/corelib/io/qsavefile/qsavefile.pro @@ -0,0 +1,5 @@ +CONFIG += testcase parallel_test +TARGET = tst_qsavefile +QT = core testlib +SOURCES = tst_qsavefile.cpp +TESTDATA += tst_qsavefile.cpp diff --git a/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp b/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp new file mode 100644 index 0000000000..5ef4b11e8a --- /dev/null +++ b/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp @@ -0,0 +1,272 @@ +/**************************************************************************** +** +** Copyright (C) 2012 David Faure <faure@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> +#include <qcoreapplication.h> +#include <qstring.h> +#include <qtemporaryfile.h> +#include <qfile.h> +#include <qdir.h> +#include <qset.h> + +#if defined(Q_OS_UNIX) +# include <unistd.h> // for geteuid +# include <sys/types.h> +#endif + +#if defined(Q_OS_WIN) +# include <windows.h> +#endif + +class tst_QSaveFile : public QObject +{ + Q_OBJECT +public slots: + +private slots: + void transactionalWrite(); + void textStreamManualFlush(); + void textStreamAutoFlush(); + void saveTwice(); + void transactionalWriteNoPermissionsOnDir(); + void transactionalWriteNoPermissionsOnFile(); + void transactionalWriteCanceled(); + void transactionalWriteErrorRenaming(); +}; + +void tst_QSaveFile::transactionalWrite() +{ + QTemporaryDir dir; + const QString targetFile = dir.path() + QString::fromLatin1("/outfile"); + QFile::remove(targetFile); + QSaveFile file(targetFile); + QVERIFY(file.open(QIODevice::WriteOnly)); + QVERIFY(file.isOpen()); + QCOMPARE(file.fileName(), targetFile); + QVERIFY(!QFile::exists(targetFile)); + + QCOMPARE(file.write("Hello"), Q_INT64_C(5)); + QCOMPARE(file.error(), QFile::NoError); + QVERIFY(!QFile::exists(targetFile)); + + QVERIFY(file.commit()); + QVERIFY(QFile::exists(targetFile)); + QCOMPARE(file.fileName(), targetFile); + + QFile reader(targetFile); + QVERIFY(reader.open(QIODevice::ReadOnly)); + QCOMPARE(QString::fromLatin1(reader.readAll()), QString::fromLatin1("Hello")); +} + +void tst_QSaveFile::saveTwice() +{ + // Check that we can reuse a QSaveFile object + // (and test the case of an existing target file) + QTemporaryDir dir; + const QString targetFile = dir.path() + QString::fromLatin1("/outfile"); + QSaveFile file(targetFile); + QVERIFY(file.open(QIODevice::WriteOnly)); + QCOMPARE(file.write("Hello"), Q_INT64_C(5)); + QVERIFY2(file.commit(), qPrintable(file.errorString())); + + QVERIFY(file.open(QIODevice::WriteOnly)); + QCOMPARE(file.write("World"), Q_INT64_C(5)); + QVERIFY2(file.commit(), qPrintable(file.errorString())); + + QFile reader(targetFile); + QVERIFY(reader.open(QIODevice::ReadOnly)); + QCOMPARE(QString::fromLatin1(reader.readAll()), QString::fromLatin1("World")); +} + +void tst_QSaveFile::textStreamManualFlush() +{ + QTemporaryDir dir; + const QString targetFile = dir.path() + QString::fromLatin1("/outfile"); + QSaveFile file(targetFile); + QVERIFY(file.open(QIODevice::WriteOnly)); + + QTextStream ts(&file); + ts << "Manual flush"; + ts.flush(); + QCOMPARE(file.error(), QFile::NoError); + QVERIFY(!QFile::exists(targetFile)); + + QVERIFY(file.commit()); + QFile reader(targetFile); + QVERIFY(reader.open(QIODevice::ReadOnly)); + QCOMPARE(QString::fromLatin1(reader.readAll().constData()), QString::fromLatin1("Manual flush")); + QFile::remove(targetFile); +} + +void tst_QSaveFile::textStreamAutoFlush() +{ + QTemporaryDir dir; + const QString targetFile = dir.path() + QString::fromLatin1("/outfile"); + QSaveFile file(targetFile); + QVERIFY(file.open(QIODevice::WriteOnly)); + + QTextStream ts(&file); + ts << "Auto-flush."; + // no flush + QVERIFY(file.commit()); // QIODevice::close will emit aboutToClose, which will flush the stream + QFile reader(targetFile); + QVERIFY(reader.open(QIODevice::ReadOnly)); + QCOMPARE(QString::fromLatin1(reader.readAll().constData()), QString::fromLatin1("Auto-flush.")); + QFile::remove(targetFile); +} + +void tst_QSaveFile::transactionalWriteNoPermissionsOnDir() +{ +#ifdef Q_OS_UNIX + if (::geteuid() == 0) + QSKIP("not valid running this test as root"); + + // You can write into /dev/zero, but you can't create a /dev/zero.XXXXXX temp file. + QSaveFile file("/dev/zero"); + if (!QDir("/dev").exists()) + QSKIP("/dev doesn't exist on this system"); + + QVERIFY(!file.open(QIODevice::WriteOnly)); + QCOMPARE((int)file.error(), (int)QFile::OpenError); + QVERIFY(!file.commit()); +#endif +} + +void tst_QSaveFile::transactionalWriteNoPermissionsOnFile() +{ + // Setup an existing but readonly file + QTemporaryDir dir; + const QString targetFile = dir.path() + QString::fromLatin1("/outfile"); + QFile file(targetFile); + QVERIFY(file.open(QIODevice::WriteOnly)); + QCOMPARE(file.write("Hello"), Q_INT64_C(5)); + file.close(); + file.setPermissions(QFile::ReadOwner); + QVERIFY(!file.open(QIODevice::WriteOnly)); + + // Try saving into it + { + QSaveFile saveFile(targetFile); + QVERIFY(!saveFile.open(QIODevice::WriteOnly)); // just like QFile + } + QVERIFY(file.exists()); +} + +void tst_QSaveFile::transactionalWriteCanceled() +{ + QTemporaryDir dir; + const QString targetFile = dir.path() + QString::fromLatin1("/outfile"); + QFile::remove(targetFile); + QSaveFile file(targetFile); + QVERIFY(file.open(QIODevice::WriteOnly)); + + QTextStream ts(&file); + ts << "This writing operation will soon be canceled.\n"; + ts.flush(); + QCOMPARE(file.error(), QFile::NoError); + QVERIFY(!QFile::exists(targetFile)); + + // We change our mind, let's abort writing + file.cancelWriting(); + + QVERIFY(!file.commit()); + + QVERIFY(!QFile::exists(targetFile)); // temp file was discarded + QCOMPARE(file.fileName(), targetFile); +} + +void tst_QSaveFile::transactionalWriteErrorRenaming() +{ + QTemporaryDir dir; + const QString targetFile = dir.path() + QString::fromLatin1("/outfile"); + QSaveFile file(targetFile); + QVERIFY(file.open(QIODevice::WriteOnly)); + QCOMPARE(file.write("Hello"), qint64(5)); + QVERIFY(!QFile::exists(targetFile)); + + // Restore permissions so that the QTemporaryDir cleanup can happen + class PermissionRestorer + { + public: + PermissionRestorer(const QString& path) + : m_path(path) + {} + + ~PermissionRestorer() + { + QFile file(m_path); +#ifdef Q_OS_UNIX + file.setPermissions(QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner)); +#else + file.setPermissions(QFile::WriteOwner); + file.remove(); +#endif + } + + private: + QString m_path; + }; + +#ifdef Q_OS_UNIX + // Make rename() fail for lack of permissions in the directory + QFile dirAsFile(dir.path()); // yay, I have to use QFile to change a dir's permissions... + QVERIFY(dirAsFile.setPermissions(QFile::Permissions(0))); // no permissions + PermissionRestorer permissionRestorer(dir.path()); +#else + // Windows: Make rename() fail for lack of permissions on an existing target file + QFile existingTargetFile(targetFile); + QVERIFY(existingTargetFile.open(QIODevice::WriteOnly)); + QCOMPARE(file.write("Target"), qint64(6)); + existingTargetFile.close(); + QVERIFY(existingTargetFile.setPermissions(QFile::ReadOwner)); + PermissionRestorer permissionRestorer(targetFile); +#endif + + // The saving should fail. + QVERIFY(!file.commit()); +#ifdef Q_OS_UNIX + QVERIFY(!QFile::exists(targetFile)); // renaming failed +#endif + QCOMPARE(file.error(), QFile::RenameError); +} + +QTEST_MAIN(tst_QSaveFile) +#include "tst_qsavefile.moc" diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp index f152c48c7d..c2909cf7c5 100644 --- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp +++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp @@ -694,7 +694,9 @@ void tst_QSettings::testErrorHandling() #ifdef Q_OS_WIN QSKIP("Windows doesn't support most file modes, including read-only directories, so this test is moot."); #elif defined(Q_OS_UNIX) +#if !defined(Q_OS_VXWORKS) // VxWorks does not have users/groups if (::getuid() == 0) +#endif QSKIP("Running this test as root doesn't work, since file perms do not bother him"); #else QFETCH(int, filePerms); diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp index 1f59336fc6..898aefffd3 100644 --- a/tests/auto/corelib/io/qurl/tst_qurl.cpp +++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp @@ -79,6 +79,8 @@ private slots: void toString(); void toString_constructed_data(); void toString_constructed(); + void toAndFromStringList_data(); + void toAndFromStringList(); void isParentOf_data(); void isParentOf(); void toLocalFile_data(); @@ -948,6 +950,25 @@ void tst_QUrl::toString() QCOMPARE(url.toString(QUrl::FormattingOptions(options)), string); } +void tst_QUrl::toAndFromStringList_data() +{ + QTest::addColumn<QStringList>("strings"); + + QTest::newRow("empty") << QStringList(); + QTest::newRow("local") << (QStringList() << "file:///tmp" << "file:///"); + QTest::newRow("remote") << (QStringList() << "http://qt-project.org"); +} + +void tst_QUrl::toAndFromStringList() +{ + QFETCH(QStringList, strings); + + const QList<QUrl> urls = QUrl::fromStringList(strings); + QCOMPARE(urls.count(), strings.count()); + const QStringList converted = QUrl::toStringList(urls); + QCOMPARE(converted, strings); +} + //### more tests ... what do we expect ... void tst_QUrl::isParentOf_data() { @@ -2163,33 +2184,52 @@ void tst_QUrl::tldRestrictions_data() // current whitelist QTest::newRow("ac") << QString("ac") << true; + QTest::newRow("ar") << QString("ar") << true; + QTest::newRow("asia") << QString("asia") << true; QTest::newRow("at") << QString("at") << true; + QTest::newRow("biz") << QString("biz") << true; QTest::newRow("br") << QString("br") << true; QTest::newRow("cat") << QString("cat") << true; QTest::newRow("ch") << QString("ch") << true; QTest::newRow("cl") << QString("cl") << true; QTest::newRow("cn") << QString("cn") << true; + QTest::newRow("com") << QString("com") << true; QTest::newRow("de") << QString("de") << true; QTest::newRow("dk") << QString("dk") << true; + QTest::newRow("es") << QString("es") << true; QTest::newRow("fi") << QString("fi") << true; + QTest::newRow("gr") << QString("gr") << true; QTest::newRow("hu") << QString("hu") << true; + QTest::newRow("il") << QString("il") << true; QTest::newRow("info") << QString("info") << true; QTest::newRow("io") << QString("io") << true; + QTest::newRow("is") << QString("is") << true; + QTest::newRow("ir") << QString("ir") << true; QTest::newRow("jp") << QString("jp") << true; QTest::newRow("kr") << QString("kr") << true; QTest::newRow("li") << QString("li") << true; QTest::newRow("lt") << QString("lt") << true; + QTest::newRow("lu") << QString("lu") << true; + QTest::newRow("lv") << QString("lv") << true; QTest::newRow("museum") << QString("museum") << true; + QTest::newRow("name") << QString("name") << true; + QTest::newRow("net") << QString("name") << true; QTest::newRow("no") << QString("no") << true; + QTest::newRow("nu") << QString("nu") << true; + QTest::newRow("nz") << QString("nz") << true; + QTest::newRow("org") << QString("org") << true; + QTest::newRow("pl") << QString("pl") << true; + QTest::newRow("pr") << QString("pr") << true; QTest::newRow("se") << QString("se") << true; QTest::newRow("sh") << QString("sh") << true; + QTest::newRow("tel") << QString("tel") << true; QTest::newRow("th") << QString("th") << true; QTest::newRow("tm") << QString("tm") << true; QTest::newRow("tw") << QString("tw") << true; + QTest::newRow("ua") << QString("ua") << true; QTest::newRow("vn") << QString("vn") << true; // known blacklists: - QTest::newRow("com") << QString("com") << false; QTest::newRow("foo") << QString("foo") << false; } @@ -2796,6 +2836,12 @@ void tst_QUrl::effectiveTLDs_data() QTest::newRow("yes6") << QUrl::fromEncoded("http://www.com.com.cn") << ".com.cn"; QTest::newRow("yes7") << QUrl::fromEncoded("http://www.test.org.ws") << ".org.ws"; QTest::newRow("yes9") << QUrl::fromEncoded("http://www.com.co.uk.wallonie.museum") << ".wallonie.museum"; + QTest::newRow("yes10") << QUrl::fromEncoded("http://www.com.evje-og-hornnes.no") << ".evje-og-hornnes.no"; + QTest::newRow("yes11") << QUrl::fromEncoded("http://www.bla.kamijima.ehime.jp") << ".kamijima.ehime.jp"; + QTest::newRow("yes12") << QUrl::fromEncoded("http://www.bla.kakuda.miyagi.jp") << ".kakuda.miyagi.jp"; + QTest::newRow("yes13") << QUrl::fromEncoded("http://mypage.betainabox.com") << ".betainabox.com"; + QTest::newRow("yes14") << QUrl::fromEncoded("http://mypage.rhcloud.com") << ".rhcloud.com"; + QTest::newRow("yes15") << QUrl::fromEncoded("http://mypage.int.az") << ".int.az"; } void tst_QUrl::effectiveTLDs() diff --git a/tests/auto/corelib/io/qurlinternal/tst_qurlinternal.cpp b/tests/auto/corelib/io/qurlinternal/tst_qurlinternal.cpp index 6ba659856c..fa3dec620a 100644 --- a/tests/auto/corelib/io/qurlinternal/tst_qurlinternal.cpp +++ b/tests/auto/corelib/io/qurlinternal/tst_qurlinternal.cpp @@ -649,6 +649,20 @@ void tst_QUrlInternal::ace_testsuite_data() << "xn----rmckbbajlc6dj7bxne2c.xn--wgbh1c" << "." << egyptianIDN; + + QString russianIDN = QString::fromUtf8("\321\217\320\275\320\264\320\265\320\272\321\201.\321\200\321\204"); + QTest::newRow("russian-tld-ace") + << "xn--d1acpjx3f.xn--p1ai" + << "xn--d1acpjx3f.xn--p1ai" + << "." + << russianIDN; + + QString taiwaneseIDN = QString::fromUtf8("\345\217\260\345\214\227\346\214\211\346\221\251.\345\217\260\347\201\243"); + QTest::newRow("taiwanese-tld-ace") + << "xn--djrptm67aikb.xn--kpry57d" + << "xn--djrptm67aikb.xn--kpry57d" + << "." + << taiwaneseIDN; } void tst_QUrlInternal::ace_testsuite() diff --git a/tests/auto/corelib/io/qwinoverlappedionotifier/tst_qwinoverlappedionotifier.cpp b/tests/auto/corelib/io/qwinoverlappedionotifier/tst_qwinoverlappedionotifier.cpp index 6e2eeced05..bad77b1e06 100644 --- a/tests/auto/corelib/io/qwinoverlappedionotifier/tst_qwinoverlappedionotifier.cpp +++ b/tests/auto/corelib/io/qwinoverlappedionotifier/tst_qwinoverlappedionotifier.cpp @@ -251,21 +251,24 @@ void tst_QWinOverlappedIoNotifier::multipleOperations() // start async read on client QByteArray clientReadBuffer(377, Qt::Uninitialized); - OVERLAPPED clientReadOverlapped = {0}; + OVERLAPPED clientReadOverlapped; + ZeroMemory(&clientReadOverlapped, sizeof(clientReadOverlapped)); BOOL readSuccess = ReadFile(hClient, clientReadBuffer.data(), clientReadBuffer.size(), NULL, &clientReadOverlapped); QVERIFY(readSuccess || GetLastError() == ERROR_IO_PENDING); // start async write client -> server QByteArray clientDataToWrite(233, 'B'); - OVERLAPPED clientWriteOverlapped = {0}; + OVERLAPPED clientWriteOverlapped; + ZeroMemory(&clientWriteOverlapped, sizeof(clientWriteOverlapped)); BOOL writeSuccess = WriteFile(hClient, clientDataToWrite.data(), clientDataToWrite.size(), NULL, &clientWriteOverlapped); QVERIFY(writeSuccess || GetLastError() == ERROR_IO_PENDING); // start async write server -> client QByteArray serverDataToWrite(144, 'A'); - OVERLAPPED serverOverlapped = {0}; + OVERLAPPED serverOverlapped; + ZeroMemory(&serverOverlapped, sizeof(serverOverlapped)); writeSuccess = WriteFile(hServer, serverDataToWrite.data(), serverDataToWrite.size(), NULL, &serverOverlapped); QVERIFY(writeSuccess || GetLastError() == ERROR_IO_PENDING); @@ -284,9 +287,9 @@ void tst_QWinOverlappedIoNotifier::multipleOperations() QTRY_COMPARE(sink.notifications.count(), 2); foreach (const NotifierSink::IOResult &r, sink.notifications) { QCOMPARE(r.errorCode, DWORD(ERROR_SUCCESS)); - if (r.bytes == serverDataToWrite.count()) + if (r.bytes == DWORD(serverDataToWrite.count())) QCOMPARE(r.overlapped, &clientReadOverlapped); - else if (r.bytes == clientDataToWrite.count()) + else if (r.bytes == DWORD(clientDataToWrite.count())) QCOMPARE(r.overlapped, &clientWriteOverlapped); else QVERIFY2(false, "Unexpected number of bytes received."); diff --git a/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp b/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp index 20bd4fa433..d2fb56ce02 100644 --- a/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp +++ b/tests/auto/corelib/itemmodels/qabstractitemmodel/tst_qabstractitemmodel.cpp @@ -467,9 +467,6 @@ typedef QPair<int, int> Position; typedef QVector<QPair<int, int> > Selection; typedef QVector<QVector<QString> > StringTable; typedef QVector<QString> StringTableRow; -Q_DECLARE_METATYPE(Position) -Q_DECLARE_METATYPE(Selection) -Q_DECLARE_METATYPE(StringTable) static StringTableRow qStringTableRow(const QString &s1, const QString &s2, const QString &s3) { @@ -1922,8 +1919,6 @@ public: void tst_QAbstractItemModel::testDataChanged() { - qRegisterMetaType<QVector<int> >(); - CustomRoleModel model; QSignalSpy withRoles(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>))); diff --git a/tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp b/tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp index c8cbacf76e..c385a02b9c 100644 --- a/tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qabstractproxymodel/tst_qabstractproxymodel.cpp @@ -281,8 +281,6 @@ void tst_QAbstractProxyModel::revert() // public void setSourceModel(QAbstractItemModel* sourceModel) void tst_QAbstractProxyModel::setSourceModel() { - qRegisterMetaType<QAbstractItemModel*>(); - SubQAbstractProxyModel model; QCOMPARE(model.property("sourceModel"), QVariant::fromValue<QAbstractItemModel*>(0)); diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp index 02a4824c4b..4578bcdab6 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp @@ -54,6 +54,8 @@ typedef QList<int> IntList; typedef QPair<int, int> IntPair; typedef QList<IntPair> IntPairList; +Q_DECLARE_METATYPE(QList<QPersistentModelIndex>) + class tst_QSortFilterProxyModel : public QObject { Q_OBJECT @@ -134,6 +136,7 @@ private slots: void testMultipleProxiesWithSelection(); void mapSelectionFromSource(); + void testResetInternalData(); void filteredColumns(); void headerDataChanged(); @@ -143,6 +146,8 @@ private slots: void hierarchyFilterInvalidation(); void simpleFilterInvalidation(); + void chainedProxyModelRoleNames(); + protected: void buildHierarchy(const QStringList &data, QAbstractItemModel *model); void checkHierarchy(const QStringList &data, const QAbstractItemModel *model); @@ -174,9 +179,7 @@ tst_QSortFilterProxyModel::tst_QSortFilterProxyModel() void tst_QSortFilterProxyModel::initTestCase() { - qRegisterMetaType<IntList>("IntList"); - qRegisterMetaType<IntPair>("IntPair"); - qRegisterMetaType<IntPairList>("IntPairList"); + qRegisterMetaType<QList<QPersistentModelIndex> >(); m_model = new QStandardItemModel(0, 1); m_proxy = new QSortFilterProxyModel(); m_proxy->setSourceModel(m_model); @@ -3242,7 +3245,142 @@ void tst_QSortFilterProxyModel::resetInvalidate() QCOMPARE(ok, works); } -Q_DECLARE_METATYPE(QList<QPersistentModelIndex>) +/** + * A proxy which changes the background color for items ending in 'y' or 'r' + */ +class CustomDataProxy : public QSortFilterProxyModel +{ + Q_OBJECT + +public: + CustomDataProxy(QObject *parent = 0) + : QSortFilterProxyModel(parent) + { + setDynamicSortFilter(true); + } + + void setSourceModel(QAbstractItemModel *sourceModel) + { + // It would be possible to use only the modelReset signal of the source model to clear + // the data in *this, however, this requires that the slot is connected + // before QSortFilterProxyModel::setSourceModel is called, and even then depends + // on the order of invocation of slots being the same as the order of connection. + // ie, not reliable. +// connect(sourceModel, SIGNAL(modelReset()), SLOT(resetInternalData())); + QSortFilterProxyModel::setSourceModel(sourceModel); + // Making the connect after the setSourceModel call clears the data too late. +// connect(sourceModel, SIGNAL(modelReset()), SLOT(resetInternalData())); + + // This could be done in data(), but the point is to need to cache something in the proxy + // which needs to be cleared on reset. + for (int i = 0; i < sourceModel->rowCount(); ++i) + { + if (sourceModel->index(i, 0).data().toString().endsWith(QLatin1Char('y'))) + { + m_backgroundColours.insert(i, Qt::blue); + } else if (sourceModel->index(i, 0).data().toString().endsWith(QLatin1Char('r'))) + { + m_backgroundColours.insert(i, Qt::red); + } + } + } + + QVariant data(const QModelIndex &index, int role) const + { + if (role != Qt::BackgroundRole) + return QSortFilterProxyModel::data(index, role); + return m_backgroundColours.value(index.row()); + } + +private slots: + void resetInternalData() + { + m_backgroundColours.clear(); + } + +private: + QHash<int, QColor> m_backgroundColours; +}; + +class ModelObserver : public QObject +{ + Q_OBJECT +public: + ModelObserver(QAbstractItemModel *model, QObject *parent = 0) + : QObject(parent), m_model(model) + { + connect(m_model, SIGNAL(modelAboutToBeReset()), SLOT(modelAboutToBeReset())); + connect(m_model, SIGNAL(modelReset()), SLOT(modelReset())); + } + +public slots: + void modelAboutToBeReset() + { + int reds = 0, blues = 0; + for (int i = 0; i < m_model->rowCount(); ++i) + { + QColor color = m_model->index(i, 0).data(Qt::BackgroundRole).value<QColor>(); + if (color == Qt::blue) + ++blues; + if (color == Qt::red) + ++reds; + } + QCOMPARE(blues, 11); + QCOMPARE(reds, 4); + } + + void modelReset() + { + int reds = 0, blues = 0; + for (int i = 0; i < m_model->rowCount(); ++i) + { + QColor color = m_model->index(i, 0).data(Qt::BackgroundRole).value<QColor>(); + if (color == Qt::blue) + ++blues; + if (color == Qt::red) + ++reds; + } + QCOMPARE(reds, 0); + QCOMPARE(blues, 0); + } + +private: + QAbstractItemModel * const m_model; + +}; + +void tst_QSortFilterProxyModel::testResetInternalData() +{ + + QStringListModel model(QStringList() << "Monday" + << "Tuesday" + << "Wednesday" + << "Thursday" + << "Friday" + << "January" + << "February" + << "March" + << "April" + << "May" + << "Saturday" + << "June" + << "Sunday" + << "July" + << "August" + << "September" + << "October" + << "November" + << "December"); + + CustomDataProxy proxy; + proxy.setSourceModel(&model); + + ModelObserver observer(&proxy); + + // Cause the source model to reset. + model.setStringList(QStringList() << "Spam" << "Eggs"); + +} void tst_QSortFilterProxyModel::testParentLayoutChanged() { @@ -3276,8 +3414,6 @@ void tst_QSortFilterProxyModel::testParentLayoutChanged() proxy2.setSourceModel(&proxy); proxy2.setObjectName("proxy2"); - qRegisterMetaType<QList<QPersistentModelIndex> >(); - QSignalSpy dataChangedSpy(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex))); QVERIFY(dataChangedSpy.isValid()); @@ -3411,8 +3547,6 @@ private: void tst_QSortFilterProxyModel::moveSourceRows() { - qRegisterMetaType<QList<QPersistentModelIndex> >(); - DynamicTreeModel model; { @@ -3635,6 +3769,45 @@ void tst_QSortFilterProxyModel::simpleFilterInvalidation() model.insertRow(0, new QStandardItem("extra")); } +class CustomRoleNameModel : public QAbstractListModel +{ + Q_OBJECT +public: + CustomRoleNameModel(QObject *parent = 0) : QAbstractListModel(parent) {} + + QVariant data(const QModelIndex &index, int role) const + { + Q_UNUSED(index); + Q_UNUSED(role); + return QVariant(); + } + + int rowCount(const QModelIndex &parent = QModelIndex()) const + { + Q_UNUSED(parent); + return 0; + } + + QHash<int, QByteArray> roleNames() const + { + QHash<int, QByteArray> rn = QAbstractListModel::roleNames(); + rn[Qt::UserRole + 1] = "custom"; + return rn; + } +}; + +void tst_QSortFilterProxyModel::chainedProxyModelRoleNames() +{ + QSortFilterProxyModel proxy1; + QSortFilterProxyModel proxy2; + CustomRoleNameModel customModel; + + proxy2.setSourceModel(&proxy1); + + // changing the sourceModel of proxy1 must also update roleNames of proxy2 + proxy1.setSourceModel(&customModel); + QVERIFY(proxy2.roleNames().value(Qt::UserRole + 1) == "custom"); +} QTEST_MAIN(tst_QSortFilterProxyModel) #include "tst_qsortfilterproxymodel.moc" diff --git a/tests/auto/corelib/json/tst_qtjson.cpp b/tests/auto/corelib/json/tst_qtjson.cpp index a692b79fe9..6811551769 100644 --- a/tests/auto/corelib/json/tst_qtjson.cpp +++ b/tests/auto/corelib/json/tst_qtjson.cpp @@ -1003,49 +1003,81 @@ void tst_QtJson::toVariantList() void tst_QtJson::toJson() { - QJsonObject object; - object.insert("\\Key\n", QString("Value")); - object.insert("null", QJsonValue()); - QJsonArray array; - array.append(true); - array.append(999.); - array.append(QLatin1String("string")); - array.append(QJsonValue()); - array.append(QLatin1String("\\\a\n\r\b\tabcABC\"")); - object.insert("Array", array); + // Test QJsonDocument::Indented format + { + QJsonObject object; + object.insert("\\Key\n", QString("Value")); + object.insert("null", QJsonValue()); + QJsonArray array; + array.append(true); + array.append(999.); + array.append(QLatin1String("string")); + array.append(QJsonValue()); + array.append(QLatin1String("\\\a\n\r\b\tabcABC\"")); + object.insert("Array", array); + + QByteArray json = QJsonDocument(object).toJson(); + + QByteArray expected = + "{\n" + " \"Array\": [\n" + " true,\n" + " 999,\n" + " \"string\",\n" + " null,\n" + " \"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"\n" + " ],\n" + " \"\\\\Key\\n\": \"Value\",\n" + " \"null\": null\n" + "}\n"; + QCOMPARE(json, expected); - QByteArray json = QJsonDocument(object).toJson(); - - QByteArray expected = - "{\n" - " \"Array\": [\n" - " true,\n" - " 999,\n" - " \"string\",\n" - " null,\n" - " \"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"\n" - " ],\n" - " \"\\\\Key\\n\": \"Value\",\n" - " \"null\": null\n" - "}\n"; - QCOMPARE(json, expected); + QJsonDocument doc; + doc.setObject(object); + json = doc.toJson(); + QCOMPARE(json, expected); - QJsonDocument doc; - doc.setObject(object); - json = doc.toJson(); - QCOMPARE(json, expected); + doc.setArray(array); + json = doc.toJson(); + expected = + "[\n" + " true,\n" + " 999,\n" + " \"string\",\n" + " null,\n" + " \"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"\n" + "]\n"; + QCOMPARE(json, expected); + } - doc.setArray(array); - json = doc.toJson(); - expected = - "[\n" - " true,\n" - " 999,\n" - " \"string\",\n" - " null,\n" - " \"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"\n" - "]\n"; - QCOMPARE(json, expected); + // Test QJsonDocument::Compact format + { + QJsonObject object; + object.insert("\\Key\n", QString("Value")); + object.insert("null", QJsonValue()); + QJsonArray array; + array.append(true); + array.append(999.); + array.append(QLatin1String("string")); + array.append(QJsonValue()); + array.append(QLatin1String("\\\a\n\r\b\tabcABC\"")); + object.insert("Array", array); + + QByteArray json = QJsonDocument(object).toJson(QJsonDocument::Compact); + QByteArray expected = + "{\"Array\": [true,999,\"string\",null,\"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"],\"\\\\Key\\n\": \"Value\",\"null\": null}"; + QCOMPARE(json, expected); + + QJsonDocument doc; + doc.setObject(object); + json = doc.toJson(QJsonDocument::Compact); + QCOMPARE(json, expected); + + doc.setArray(array); + json = doc.toJson(QJsonDocument::Compact); + expected = "[true,999,\"string\",null,\"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"]"; + QCOMPARE(json, expected); + } } void tst_QtJson::fromJson() @@ -1135,6 +1167,30 @@ void tst_QtJson::fromJson() QCOMPARE(object.value("6").type(), QJsonValue::Object); QCOMPARE(object.value("6").toObject().size(), 0); } + { + QByteArray compactJson = "{\"Array\": [true,999,\"string\",null,\"\\\\\\u0007\\n\\r\\b\\tabcABC\\\"\"],\"\\\\Key\\n\": \"Value\",\"null\": null}"; + QJsonDocument doc = QJsonDocument::fromJson(compactJson); + QVERIFY(!doc.isEmpty()); + QCOMPARE(doc.isArray(), false); + QCOMPARE(doc.isObject(), true); + QJsonObject object = doc.object(); + QCOMPARE(object.size(), 3); + QCOMPARE(object.value("\\Key\n").isString(), true); + QCOMPARE(object.value("\\Key\n").toString(), QString("Value")); + QCOMPARE(object.value("null").isNull(), true); + QCOMPARE(object.value("Array").isArray(), true); + QJsonArray array = object.value("Array").toArray(); + QCOMPARE(array.size(), 5); + QCOMPARE(array.at(0).isBool(), true); + QCOMPARE(array.at(0).toBool(), true); + QCOMPARE(array.at(1).isDouble(), true); + QCOMPARE(array.at(1).toDouble(), 999.); + QCOMPARE(array.at(2).isString(), true); + QCOMPARE(array.at(2).toString(), QLatin1String("string")); + QCOMPARE(array.at(3).isNull(), true); + QCOMPARE(array.at(4).isString(), true); + QCOMPARE(array.at(4).toString(), QLatin1String("\\\a\n\r\b\tabcABC\"")); + } } void tst_QtJson::fromJsonErrors() diff --git a/tests/auto/corelib/kernel/kernel.pro b/tests/auto/corelib/kernel/kernel.pro index 839d652be1..24b4c6d6eb 100644 --- a/tests/auto/corelib/kernel/kernel.pro +++ b/tests/auto/corelib/kernel/kernel.pro @@ -21,6 +21,11 @@ SUBDIRS=\ qvariant \ qwineventnotifier +!qtHaveModule(network): SUBDIRS -= \ + qeventloop \ + qobject \ + qsocketnotifier + !contains(QT_CONFIG, private_tests): SUBDIRS -= \ qsocketnotifier \ qsharedmemory diff --git a/tests/auto/corelib/kernel/qmath/tst_qmath.cpp b/tests/auto/corelib/kernel/qmath/tst_qmath.cpp index 0d977317ca..a1ca2ca8cb 100644 --- a/tests/auto/corelib/kernel/qmath/tst_qmath.cpp +++ b/tests/auto/corelib/kernel/qmath/tst_qmath.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org> ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. @@ -49,6 +50,10 @@ class tst_QMath : public QObject Q_OBJECT private slots: void fastSinCos(); + void degreesToRadians_data(); + void degreesToRadians(); + void radiansToDegrees_data(); + void radiansToDegrees(); }; void tst_QMath::fastSinCos() @@ -62,6 +67,76 @@ void tst_QMath::fastSinCos() } } +void tst_QMath::degreesToRadians_data() +{ + QTest::addColumn<float>("degreesFloat"); + QTest::addColumn<float>("radiansFloat"); + QTest::addColumn<double>("degreesDouble"); + QTest::addColumn<double>("radiansDouble"); + + QTest::newRow( "pi" ) << 180.0f << float(M_PI) << 180.0 << PI; + QTest::newRow( "doublepi" ) << 360.0f << float(2*M_PI) << 360.0 << 2*PI; + QTest::newRow( "halfpi" ) << 90.0f << float(M_PI_2) << 90.0 << PI/2; + + QTest::newRow( "random" ) << 123.1234567f << 2.1489097058516724f << 123.123456789123456789 << 2.148909707407169856192285627; + QTest::newRow( "bigrandom" ) << 987654321.9876543f << 17237819.79023679f << 987654321987654321.987654321987654321 << 17237819790236794.0; + + QTest::newRow( "zero" ) << 0.0f << 0.0f << 0.0 << 0.0; + + QTest::newRow( "minuspi" ) << -180.0f << float(-M_PI) << 180.0 << PI; + QTest::newRow( "minusdoublepi" ) << -360.0f << float(-2*M_PI) << -360.0 << -2*PI; + QTest::newRow( "minushalfpi" ) << -90.0f << float(-M_PI_2) << -90.0 << -PI/2; + + QTest::newRow( "minusrandom" ) << -123.1234567f << -2.1489097058516724f << -123.123456789123456789 << -2.148909707407169856192285627; + QTest::newRow( "minusbigrandom" ) << -987654321.9876543f << -17237819.79023679f << -987654321987654321.987654321987654321 << -17237819790236794.0; +} + +void tst_QMath::degreesToRadians() +{ + QFETCH(float, degreesFloat); + QFETCH(float, radiansFloat); + QFETCH(double, degreesDouble); + QFETCH(double, radiansDouble); + + QCOMPARE(qDegreesToRadians(degreesFloat), radiansFloat); + QCOMPARE(qDegreesToRadians(degreesDouble), radiansDouble); +} + +void tst_QMath::radiansToDegrees_data() +{ + QTest::addColumn<float>("radiansFloat"); + QTest::addColumn<float>("degreesFloat"); + QTest::addColumn<double>("radiansDouble"); + QTest::addColumn<double>("degreesDouble"); + + QTest::newRow( "pi" ) << float(M_PI) << 180.0f << PI << 180.0; + QTest::newRow( "doublepi" ) << float(2*M_PI) << 360.0f << 2*PI << 360.0; + QTest::newRow( "halfpi" ) << float(M_PI_2) << 90.0f<< PI/2 << 90.0; + + QTest::newRow( "random" ) << 123.1234567f << 7054.454427971739f << 123.123456789123456789 << 7054.4544330781363896676339209079742431640625; + QTest::newRow( "bigrandom" ) << 987654321.9876543f << 56588424267.74745f << 987654321987654321.987654321987654321 << 56588424267747450880.0; + + QTest::newRow( "zero" ) << 0.0f << 0.0f << 0.0 << 0.0; + + QTest::newRow( "minuspi" ) << float(-M_PI) << -180.0f << -PI << -180.0; + QTest::newRow( "minusdoublepi" ) << float(-2*M_PI) << -360.0f << -2*PI << -360.0; + QTest::newRow( "minushalfpi" ) << float(-M_PI_2) << -90.0f << -PI/2 << -90.0; + + QTest::newRow( "minusrandom" ) << -123.1234567f << -7054.454427971739f << -123.123456789123456789 << -7054.4544330781363896676339209079742431640625; + QTest::newRow( "minusbigrandom" ) << -987654321.9876543f << -56588424267.74745f << -987654321987654321.987654321987654321 << -56588424267747450880.0; +} + +void tst_QMath::radiansToDegrees() +{ + QFETCH(float, radiansFloat); + QFETCH(float, degreesFloat); + QFETCH(double, radiansDouble); + QFETCH(double, degreesDouble); + + QCOMPARE(qRadiansToDegrees(radiansFloat), degreesFloat); + QCOMPARE(qRadiansToDegrees(radiansDouble), degreesDouble); +} + QTEST_APPLESS_MAIN(tst_QMath) #include "tst_qmath.moc" diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index 7f7486ef4b..9a75bad549 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -110,6 +110,7 @@ private slots: void saveAndLoadCustom(); void metaObject(); void constexprMetaTypeIds(); + void constRefs(); }; struct Foo { int i; }; @@ -1762,6 +1763,17 @@ void tst_QMetaType::constexprMetaTypeIds() #endif } +void tst_QMetaType::constRefs() +{ + QCOMPARE(::qMetaTypeId<const int &>(), ::qMetaTypeId<int>()); + QCOMPARE(::qMetaTypeId<const QString &>(), ::qMetaTypeId<QString>()); + QCOMPARE(::qMetaTypeId<const CustomMovable &>(), ::qMetaTypeId<CustomMovable>()); + QCOMPARE(::qMetaTypeId<const QList<CustomMovable> &>(), ::qMetaTypeId<QList<CustomMovable> >()); +#if defined(Q_COMPILER_CONSTEXPR) + Q_STATIC_ASSERT(::qMetaTypeId<const int &>() == ::qMetaTypeId<int>()); +#endif +} + // Compile-time test, it should be possible to register function pointer types class Undefined; diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 865264c43a..0521c2277c 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com> ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. @@ -140,10 +141,21 @@ private slots: void returnValue2_data(); void returnValue2(); void connectVirtualSlots(); + void connectPrivateSlots(); void connectFunctorArgDifference(); void disconnectDoesNotLeakFunctor(); }; +struct QObjectCreatedOnShutdown +{ + QObjectCreatedOnShutdown() {} + ~QObjectCreatedOnShutdown() + { + QObject(); + } +}; +static QObjectCreatedOnShutdown s_qobjectCreatedOnShutdown; + class SenderObject : public QObject { Q_OBJECT @@ -1436,9 +1448,11 @@ public: public slots: void slot1(CustomType ct); + void slot2(const QList<CustomType> &ct); signals: void signal1(CustomType ct); + void signal2(const QList<CustomType> &ct); public: CustomType received; @@ -1447,6 +1461,8 @@ public: void QCustomTypeChecker::slot1(CustomType ct) { received = ct; } +void QCustomTypeChecker::slot2(const QList< CustomType >& ct) +{ received = ct[0]; } void tst_QObject::customTypes() { @@ -4657,6 +4673,21 @@ void tst_QObject::customTypesPointer() QCOMPARE(qRegisterMetaType<CustomType>("CustomType"), idx); QCOMPARE(QMetaType::type("CustomType"), idx); QVERIFY(QMetaType::isRegistered(idx)); + + // Test auto registered type (QList<CustomType>) + QList<CustomType> list; + QCOMPARE(instanceCount, 4); + list.append(t1); + QCOMPARE(instanceCount, 5); + QVERIFY(connect(&checker, &QCustomTypeChecker::signal2, + &checker, &QCustomTypeChecker::slot2, Qt::QueuedConnection)); + emit checker.signal2(list); + QCOMPARE(instanceCount, 5); //because the list is implicitly shared. + list.clear(); + QCOMPARE(instanceCount, 5); + QCoreApplication::processEvents(); + QCOMPARE(checker.received.value(), t1.value()); + QCOMPARE(instanceCount, 4); } QCOMPARE(instanceCount, 3); } @@ -5535,6 +5566,72 @@ void tst_QObject::connectVirtualSlots() */ } +#ifndef QT_BUILD_INTERNAL +void tst_QObject::connectPrivateSlots() +{QSKIP("Needs QT_BUILD_INTERNAL");} +#else +class ConnectToPrivateSlotPrivate; + +class ConnectToPrivateSlot :public QObject { + Q_OBJECT +public: + ConnectToPrivateSlot(); + void test(SenderObject *obj1) ; + Q_DECLARE_PRIVATE(ConnectToPrivateSlot) +}; + +class ConnectToPrivateSlotPrivate : public QObjectPrivate { +public: + Q_DECLARE_PUBLIC(ConnectToPrivateSlot) + int receivedCount; + QVariant receivedValue; + + void thisIsAPrivateSlot() { + receivedCount++; + }; + + void thisIsAPrivateSlotWithArg(const QVariant &v) { + receivedCount++; + receivedValue = v; + }; +}; + +ConnectToPrivateSlot::ConnectToPrivateSlot(): QObject(*new ConnectToPrivateSlotPrivate) {} + +void ConnectToPrivateSlot::test(SenderObject* obj1) { + Q_D(ConnectToPrivateSlot); + d->receivedCount = 0; + QVERIFY(QObjectPrivate::connect(obj1, &SenderObject::signal1, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot)); + QVERIFY(QObjectPrivate::connect(obj1, &SenderObject::signal7, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlotWithArg)); + QCOMPARE(d->receivedCount, 0); + obj1->signal1(); + QCOMPARE(d->receivedCount, 1); + QCOMPARE(d->receivedValue, QVariant()); + obj1->signal7(666, QLatin1Literal("_")); + QCOMPARE(d->receivedCount, 2); + QCOMPARE(d->receivedValue, QVariant(666)); + QVERIFY(QObjectPrivate::connect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot, Qt::UniqueConnection)); + QVERIFY(!QObjectPrivate::connect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot, Qt::UniqueConnection)); + obj1->signal2(); + QCOMPARE(d->receivedCount, 3); + QVERIFY(QObjectPrivate::disconnect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot)); + obj1->signal2(); + QCOMPARE(d->receivedCount, 3); + QVERIFY(!QObjectPrivate::disconnect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot)); +} + +void tst_QObject::connectPrivateSlots() +{ + SenderObject sender; + { + ConnectToPrivateSlot o; + o.test(&sender); + } + sender.signal7(777, QLatin1String("check that deleting the object properly disconnected")); + sender.signal1(); +} +#endif + struct SlotFunctor { void operator()() {} diff --git a/tests/auto/corelib/kernel/qpointer/tst_qpointer.cpp b/tests/auto/corelib/kernel/qpointer/tst_qpointer.cpp index 7c6549364f..609b4b7dce 100644 --- a/tests/auto/corelib/kernel/qpointer/tst_qpointer.cpp +++ b/tests/auto/corelib/kernel/qpointer/tst_qpointer.cpp @@ -65,6 +65,7 @@ private slots: void threadSafety(); void qvariantCast(); + void constPointer(); }; void tst_QPointer::constructors() @@ -384,6 +385,12 @@ void tst_QPointer::qvariantCast() // QPointer<int> sop = qPointerFromVariant<int>(v); } +void tst_QPointer::constPointer() +{ + // Compile-time test that QPointer<const T> works. + QPointer<const QFile> fp = new QFile; + delete fp.data(); +} QTEST_MAIN(tst_QPointer) diff --git a/tests/auto/corelib/plugin/qpluginloader/lib/mylib.c b/tests/auto/corelib/plugin/qpluginloader/lib/mylib.c index 324dce5b0c..a9abe471b1 100644 --- a/tests/auto/corelib/plugin/qpluginloader/lib/mylib.c +++ b/tests/auto/corelib/plugin/qpluginloader/lib/mylib.c @@ -53,6 +53,12 @@ # define BORLAND_STDCALL #endif +static int pluginVariable = 0xc0ffee; +LIB_EXPORT int *pointerAddress() +{ + return &pluginVariable; +} + LIB_EXPORT int BORLAND_STDCALL version() { return 1; diff --git a/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.cpp b/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.cpp index 6abb9b6c20..b26b24f454 100644 --- a/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.cpp +++ b/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.cpp @@ -46,3 +46,9 @@ QString ThePlugin::pluginName() const { return QLatin1String("Plugin ok"); } + +static int pluginVariable = 0xc0ffee; +extern "C" Q_DECL_EXPORT int *pointerAddress() +{ + return &pluginVariable; +} diff --git a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp index f0be8cf6f1..cef4f53101 100644 --- a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp +++ b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp @@ -99,13 +99,19 @@ static QString sys_qualifiedLibraryName(const QString &fileName) { - return QFINDTESTDATA(QString("bin/%1%2%3").arg(PREFIX).arg(fileName).arg(SUFFIX)); + QString libname = QFINDTESTDATA(QString("bin/%1%2%3").arg(PREFIX).arg(fileName).arg(SUFFIX)); + QFileInfo fi(libname); + if (fi.exists()) + return fi.canonicalFilePath(); + return libname; } QT_FORWARD_DECLARE_CLASS(QPluginLoader) class tst_QPluginLoader : public QObject { Q_OBJECT +public slots: + void cleanup(); private slots: void errorString(); void loadHints(); @@ -117,8 +123,25 @@ private slots: #endif void relativePath(); void reloadPlugin(); + void preloadedPlugin_data(); + void preloadedPlugin(); }; +void tst_QPluginLoader::cleanup() +{ + // check if the library/plugin was leaked + // we can't use QPluginLoader::isLoaded here because on some platforms the plugin is always loaded by QPluginLoader. + // Also, if this test fails once, it will keep on failing because we can't force the unload, + // so we report it only once. + static bool failedAlready = false; + if (!failedAlready) { + QLibrary lib(sys_qualifiedLibraryName("theplugin")); + failedAlready = true; + QVERIFY2(!lib.isLoaded(), "Plugin was leaked - will not check again"); + failedAlready = false; + } +} + void tst_QPluginLoader::errorString() { #if defined(Q_OS_WINCE) @@ -334,6 +357,50 @@ void tst_QPluginLoader::reloadPlugin() PluginInterface *instance2 = qobject_cast<PluginInterface*>(loader.instance()); QVERIFY(instance2); QCOMPARE(instance2->pluginName(), QLatin1String("Plugin ok")); + + QVERIFY(loader.unload()); +} + +void tst_QPluginLoader::preloadedPlugin_data() +{ + QTest::addColumn<bool>("doLoad"); + QTest::addColumn<QString>("libname"); + QTest::newRow("create-plugin") << false << sys_qualifiedLibraryName("theplugin"); + QTest::newRow("load-plugin") << true << sys_qualifiedLibraryName("theplugin"); + QTest::newRow("create-non-plugin") << false << sys_qualifiedLibraryName("tst_qpluginloaderlib"); + QTest::newRow("load-non-plugin") << true << sys_qualifiedLibraryName("tst_qpluginloaderlib"); +} + +void tst_QPluginLoader::preloadedPlugin() +{ + // check that using QPluginLoader does not interfere with QLibrary + QFETCH(QString, libname); + QLibrary lib(libname); + QVERIFY(lib.load()); + + typedef int *(*pf_t)(); + pf_t pf = (pf_t)lib.resolve("pointerAddress"); + QVERIFY(pf); + + int *pluginVariable = pf(); + QVERIFY(pluginVariable); + QCOMPARE(*pluginVariable, 0xc0ffee); + + { + // load the plugin + QPluginLoader loader(libname); + QFETCH(bool, doLoad); + if (doLoad && loader.load()) { + // unload() returns false because QLibrary has it loaded + QVERIFY(!loader.unload()); + } + } + + QVERIFY(lib.isLoaded()); + + // if the library was unloaded behind our backs, the following will crash: + QCOMPARE(*pluginVariable, 0xc0ffee); + QVERIFY(lib.unload()); } QTEST_MAIN(tst_QPluginLoader) diff --git a/tests/auto/corelib/thread/qthreadonce/qthreadonce.h b/tests/auto/corelib/thread/qthreadonce/qthreadonce.h index eff7924410..5e04a16bb9 100644 --- a/tests/auto/corelib/thread/qthreadonce/qthreadonce.h +++ b/tests/auto/corelib/thread/qthreadonce/qthreadonce.h @@ -46,8 +46,6 @@ #include <QtCore/qglobal.h> #include <QtCore/qatomic.h> -QT_BEGIN_HEADER - #ifndef QT_NO_THREAD @@ -108,6 +106,4 @@ public: #endif // QT_NO_THREAD -QT_END_HEADER - #endif diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp index a586f81ccc..57a43a2b33 100644 --- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp +++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp @@ -64,6 +64,12 @@ QRunnable *createTask(FunctionPointer pointer) class tst_QThreadPool : public QObject { Q_OBJECT +public: + tst_QThreadPool(); + ~tst_QThreadPool(); + + static QMutex *functionTestMutex; + private slots: void runFunction(); void createThreadRunFunction(); @@ -92,8 +98,24 @@ private slots: void waitForDoneTimeout(); void destroyingWaitsForTasksToFinish(); void stressTest(); + +private: + QMutex m_functionTestMutex; }; + +QMutex *tst_QThreadPool::functionTestMutex = 0; + +tst_QThreadPool::tst_QThreadPool() +{ + tst_QThreadPool::functionTestMutex = &m_functionTestMutex; +} + +tst_QThreadPool::~tst_QThreadPool() +{ + tst_QThreadPool::functionTestMutex = 0; +} + int testFunctionCount; void sleepTestFunction() @@ -114,19 +136,19 @@ void noSleepTestFunction() void sleepTestFunctionMutex() { - static QMutex testMutex; + Q_ASSERT(tst_QThreadPool::functionTestMutex); QTest::qSleep(1000); - testMutex.lock(); + tst_QThreadPool::functionTestMutex->lock(); ++testFunctionCount; - testMutex.unlock(); + tst_QThreadPool::functionTestMutex->unlock(); } void noSleepTestFunctionMutex() { - static QMutex testMutex; - testMutex.lock(); + Q_ASSERT(tst_QThreadPool::functionTestMutex); + tst_QThreadPool::functionTestMutex->lock(); ++testFunctionCount; - testMutex.unlock(); + tst_QThreadPool::functionTestMutex->unlock(); } void tst_QThreadPool::runFunction() diff --git a/tests/auto/corelib/tools/qchar/tst_qchar.cpp b/tests/auto/corelib/tools/qchar/tst_qchar.cpp index 478747bf15..c89d553112 100644 --- a/tests/auto/corelib/tools/qchar/tst_qchar.cpp +++ b/tests/auto/corelib/tools/qchar/tst_qchar.cpp @@ -709,40 +709,40 @@ void tst_QChar::lineBreakClass() void tst_QChar::script() { - QVERIFY(QUnicodeTables::script(0x0020u) == QUnicodeTables::Common); - QVERIFY(QUnicodeTables::script(0x0041u) == QUnicodeTables::Common); // ### Latin - QVERIFY(QUnicodeTables::script(0x0375u) == QUnicodeTables::Greek); - QVERIFY(QUnicodeTables::script(0x0400u) == QUnicodeTables::Cyrillic); - QVERIFY(QUnicodeTables::script(0x0531u) == QUnicodeTables::Armenian); - QVERIFY(QUnicodeTables::script(0x0591u) == QUnicodeTables::Hebrew); - QVERIFY(QUnicodeTables::script(0x0600u) == QUnicodeTables::Arabic); - QVERIFY(QUnicodeTables::script(0x0700u) == QUnicodeTables::Syriac); - QVERIFY(QUnicodeTables::script(0x0780u) == QUnicodeTables::Thaana); - QVERIFY(QUnicodeTables::script(0x07c0u) == QUnicodeTables::Nko); - QVERIFY(QUnicodeTables::script(0x0900u) == QUnicodeTables::Devanagari); - QVERIFY(QUnicodeTables::script(0x0981u) == QUnicodeTables::Bengali); - QVERIFY(QUnicodeTables::script(0x0a01u) == QUnicodeTables::Gurmukhi); - QVERIFY(QUnicodeTables::script(0x0a81u) == QUnicodeTables::Gujarati); - QVERIFY(QUnicodeTables::script(0x0b01u) == QUnicodeTables::Oriya); - QVERIFY(QUnicodeTables::script(0x0b82u) == QUnicodeTables::Tamil); - QVERIFY(QUnicodeTables::script(0x0c01u) == QUnicodeTables::Telugu); - QVERIFY(QUnicodeTables::script(0x0c82u) == QUnicodeTables::Kannada); - QVERIFY(QUnicodeTables::script(0x0d02u) == QUnicodeTables::Malayalam); - QVERIFY(QUnicodeTables::script(0x0d82u) == QUnicodeTables::Sinhala); - QVERIFY(QUnicodeTables::script(0x0e01u) == QUnicodeTables::Thai); - QVERIFY(QUnicodeTables::script(0x0e81u) == QUnicodeTables::Lao); - QVERIFY(QUnicodeTables::script(0x0f00u) == QUnicodeTables::Tibetan); - QVERIFY(QUnicodeTables::script(0x1000u) == QUnicodeTables::Myanmar); - QVERIFY(QUnicodeTables::script(0x10a0u) == QUnicodeTables::Georgian); - QVERIFY(QUnicodeTables::script(0x1100u) == QUnicodeTables::Hangul); - QVERIFY(QUnicodeTables::script(0x1680u) == QUnicodeTables::Ogham); - QVERIFY(QUnicodeTables::script(0x16a0u) == QUnicodeTables::Runic); - QVERIFY(QUnicodeTables::script(0x1780u) == QUnicodeTables::Khmer); - QVERIFY(QUnicodeTables::script(0x200cu) == QUnicodeTables::Inherited); - QVERIFY(QUnicodeTables::script(0x200du) == QUnicodeTables::Inherited); - QVERIFY(QUnicodeTables::script(0x1018au) == QUnicodeTables::Greek); - QVERIFY(QUnicodeTables::script(0x1f130u) == QUnicodeTables::Common); - QVERIFY(QUnicodeTables::script(0xe0100u) == QUnicodeTables::Inherited); + QVERIFY(QChar::script(0x0020u) == QChar::Script_Common); + QVERIFY(QChar::script(0x0041u) == QChar::Script_Latin); + QVERIFY(QChar::script(0x0375u) == QChar::Script_Greek); + QVERIFY(QChar::script(0x0400u) == QChar::Script_Cyrillic); + QVERIFY(QChar::script(0x0531u) == QChar::Script_Armenian); + QVERIFY(QChar::script(0x0591u) == QChar::Script_Hebrew); + QVERIFY(QChar::script(0x0600u) == QChar::Script_Arabic); + QVERIFY(QChar::script(0x0700u) == QChar::Script_Syriac); + QVERIFY(QChar::script(0x0780u) == QChar::Script_Thaana); + QVERIFY(QChar::script(0x07c0u) == QChar::Script_Nko); + QVERIFY(QChar::script(0x0900u) == QChar::Script_Devanagari); + QVERIFY(QChar::script(0x0981u) == QChar::Script_Bengali); + QVERIFY(QChar::script(0x0a01u) == QChar::Script_Gurmukhi); + QVERIFY(QChar::script(0x0a81u) == QChar::Script_Gujarati); + QVERIFY(QChar::script(0x0b01u) == QChar::Script_Oriya); + QVERIFY(QChar::script(0x0b82u) == QChar::Script_Tamil); + QVERIFY(QChar::script(0x0c01u) == QChar::Script_Telugu); + QVERIFY(QChar::script(0x0c82u) == QChar::Script_Kannada); + QVERIFY(QChar::script(0x0d02u) == QChar::Script_Malayalam); + QVERIFY(QChar::script(0x0d82u) == QChar::Script_Sinhala); + QVERIFY(QChar::script(0x0e01u) == QChar::Script_Thai); + QVERIFY(QChar::script(0x0e81u) == QChar::Script_Lao); + QVERIFY(QChar::script(0x0f00u) == QChar::Script_Tibetan); + QVERIFY(QChar::script(0x1000u) == QChar::Script_Myanmar); + QVERIFY(QChar::script(0x10a0u) == QChar::Script_Georgian); + QVERIFY(QChar::script(0x1100u) == QChar::Script_Hangul); + QVERIFY(QChar::script(0x1680u) == QChar::Script_Ogham); + QVERIFY(QChar::script(0x16a0u) == QChar::Script_Runic); + QVERIFY(QChar::script(0x1780u) == QChar::Script_Khmer); + QVERIFY(QChar::script(0x200cu) == QChar::Script_Inherited); + QVERIFY(QChar::script(0x200du) == QChar::Script_Inherited); + QVERIFY(QChar::script(0x1018au) == QChar::Script_Greek); + QVERIFY(QChar::script(0x1f130u) == QChar::Script_Common); + QVERIFY(QChar::script(0xe0100u) == QChar::Script_Inherited); } void tst_QChar::normalization_data() diff --git a/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp b/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp index 5ba2f2920a..e941ceb456 100644 --- a/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp +++ b/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp @@ -52,6 +52,7 @@ private slots: void intermediary_result_data(); void intermediary_result(); void sha1(); + void sha3(); void files_data(); void files(); }; @@ -118,6 +119,23 @@ void tst_QCryptographicHash::intermediary_result_data() << QByteArray("abc") << QByteArray("abc") << QByteArray::fromHex("DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA20A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F") << QByteArray::fromHex("F3C41E7B63EE869596FC28BAD64120612C520F65928AB4D126C72C6998B551B8FF1CEDDFED4373E6717554DC89D1EEE6F0AB22FD3675E561ABA9AE26A3EEC53B"); + + QTest::newRow("sha3_224") << int(QCryptographicHash::Sha3_224) + << QByteArray("abc") << QByteArray("abc") + << QByteArray::fromHex("C30411768506EBE1C2871B1EE2E87D38DF342317300A9B97A95EC6A8") + << QByteArray::fromHex("048330E7C7C8B4A41AB713B3A6F958D77B8CF3EE969930F1584DD550"); + QTest::newRow("sha3_256") << int(QCryptographicHash::Sha3_256) + << QByteArray("abc") << QByteArray("abc") + << QByteArray::fromHex("4E03657AEA45A94FC7D47BA826C8D667C0D1E6E33A64A036EC44F58FA12D6C45") + << QByteArray::fromHex("9F0ADAD0A59B05D2E04A1373342B10B9EB16C57C164C8A3BFCBF46DCCEE39A21"); + QTest::newRow("sha3_384") << int(QCryptographicHash::Sha3_384) + << QByteArray("abc") << QByteArray("abc") + << QByteArray::fromHex("F7DF1165F033337BE098E7D288AD6A2F74409D7A60B49C36642218DE161B1F99F8C681E4AFAF31A34DB29FB763E3C28E") + << QByteArray::fromHex("D733B87D392D270889D3DA23AE113F349E25574B445F319CDE4CD3F877C753E9E3C65980421339B3A131457FF393939F"); + QTest::newRow("sha3_512") << int(QCryptographicHash::Sha3_512) + << QByteArray("abc") << QByteArray("abc") + << QByteArray::fromHex("18587DC2EA106B9A1563E32B3312421CA164C7F1F07BC922A9C83D77CEA3A1E5D0C69910739025372DC14AC9642629379540C17E2A65B19D77AA511A9D00BB96") + << QByteArray::fromHex("A7C392D2A42155761CA76BDDDE1C47D55486B007EDF465397BFB9DFA74D11C8F0D7C86CD29415283F1B5E7F655CEC25B869C9E9C33A8986F0B38542FB12BFB93"); } void tst_QCryptographicHash::intermediary_result() @@ -167,6 +185,55 @@ void tst_QCryptographicHash::sha1() QByteArray("34AA973CD4C4DAA4F61EEB2BDBAD27316534016F")); } +void tst_QCryptographicHash::sha3() +{ + // SHA3-224("The quick brown fox jumps over the lazy dog") + // 10aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe + QCOMPARE(QCryptographicHash::hash("The quick brown fox jumps over the lazy dog", + QCryptographicHash::Sha3_224).toHex(), + QByteArray("310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe")); + // SHA3-224("The quick brown fox jumps over the lazy dog.") + // c59d4eaeac728671c635ff645014e2afa935bebffdb5fbd207ffdeab + QCOMPARE(QCryptographicHash::hash("The quick brown fox jumps over the lazy dog.", + QCryptographicHash::Sha3_224).toHex(), + QByteArray("c59d4eaeac728671c635ff645014e2afa935bebffdb5fbd207ffdeab")); + + // SHA3-256("The quick brown fox jumps over the lazy dog") + // 4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15 + QCOMPARE(QCryptographicHash::hash("The quick brown fox jumps over the lazy dog", + QCryptographicHash::Sha3_256).toHex(), + QByteArray("4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15")); + + // SHA3-256("The quick brown fox jumps over the lazy dog.") + // 578951e24efd62a3d63a86f7cd19aaa53c898fe287d2552133220370240b572d + QCOMPARE(QCryptographicHash::hash("The quick brown fox jumps over the lazy dog.", + QCryptographicHash::Sha3_256).toHex(), + QByteArray("578951e24efd62a3d63a86f7cd19aaa53c898fe287d2552133220370240b572d")); + + // SHA3-384("The quick brown fox jumps over the lazy dog") + // 283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3 + QCOMPARE(QCryptographicHash::hash("The quick brown fox jumps over the lazy dog", + QCryptographicHash::Sha3_384).toHex(), + QByteArray("283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3")); + + // SHA3-384("The quick brown fox jumps over the lazy dog.") + // 9ad8e17325408eddb6edee6147f13856ad819bb7532668b605a24a2d958f88bd5c169e56dc4b2f89ffd325f6006d820b + QCOMPARE(QCryptographicHash::hash("The quick brown fox jumps over the lazy dog.", + QCryptographicHash::Sha3_384).toHex(), + QByteArray("9ad8e17325408eddb6edee6147f13856ad819bb7532668b605a24a2d958f88bd5c169e56dc4b2f89ffd325f6006d820b")); + + // SHA3-512("The quick brown fox jumps over the lazy dog") + // d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609 + QCOMPARE(QCryptographicHash::hash("The quick brown fox jumps over the lazy dog", + QCryptographicHash::Sha3_512).toHex(), + QByteArray("d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609")); + + // SHA3-512("The quick brown fox jumps over the lazy dog.") + // ab7192d2b11f51c7dd744e7b3441febf397ca07bf812cceae122ca4ded6387889064f8db9230f173f6d1ab6e24b6e50f065b039f799f5592360a6558eb52d760 + QCOMPARE(QCryptographicHash::hash("The quick brown fox jumps over the lazy dog.", + QCryptographicHash::Sha3_512).toHex(), + QByteArray("ab7192d2b11f51c7dd744e7b3441febf397ca07bf812cceae122ca4ded6387889064f8db9230f173f6d1ab6e24b6e50f065b039f799f5592360a6558eb52d760")); +} Q_DECLARE_METATYPE(QCryptographicHash::Algorithm); diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index 05a6c6b252..4e5b0a3555 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -145,6 +145,8 @@ private: QDateTime invalidDateTime() const { return QDateTime(invalidDate(), invalidTime()); } QDate invalidDate() const { return QDate(); } QTime invalidTime() const { return QTime(-1, -1, -1); } + qint64 minJd() const { return QDateTimePrivate::minJd(); } + qint64 maxJd() const { return QDateTimePrivate::maxJd(); } }; Q_DECLARE_METATYPE(Qt::TimeSpec) @@ -462,14 +464,25 @@ void tst_QDateTime::setMSecsSinceEpoch_data() << (Q_INT64_C(123456) << 32) << QDateTime(QDate(18772, 8, 15), QTime(1, 8, 14, 976), Qt::UTC) << QDateTime(QDate(18772, 8, 15), QTime(3, 8, 14, 976)); - QTest::newRow("min_date") // julian day 0 is an invalid date for QDate + QTest::newRow("old min (Tue Nov 25 00:00:00 -4714)") << Q_INT64_C(-210866716800000) << QDateTime(QDate::fromJulianDay(1), QTime(), Qt::UTC) << QDateTime(QDate::fromJulianDay(1), QTime(1, 0)); - QTest::newRow("max_date") // technically jd is unsigned, but fromJulianDay takes int + QTest::newRow("old max (Tue Jun 3 21:59:59 5874898)") << Q_INT64_C(185331720376799999) << QDateTime(QDate::fromJulianDay(0x7fffffff), QTime(21, 59, 59, 999), Qt::UTC) << QDateTime(QDate::fromJulianDay(0x7fffffff), QTime(23, 59, 59, 999)); + QTest::newRow("min") + // + 1 because, in the reference check below, calling addMSecs(qint64min) + // will internally apply unary minus to -qint64min, resulting in a + // positive value 1 too big for qint64max, causing an overflow. + << std::numeric_limits<qint64>::min() + 1 + << QDateTime(QDate(-292275056, 5, 16), QTime(16, 47, 4, 193), Qt::UTC) + << QDateTime(QDate(-292275056, 5, 16), QTime(17, 47, 4, 193), Qt::LocalTime); + QTest::newRow("max") + << std::numeric_limits<qint64>::max() + << QDateTime(QDate(292278994, 8, 17), QTime(7, 12, 55, 807), Qt::UTC) + << QDateTime(QDate(292278994, 8, 17), QTime(9, 12, 55, 807), Qt::LocalTime); } void tst_QDateTime::setMSecsSinceEpoch() @@ -821,6 +834,29 @@ void tst_QDateTime::toTimeSpec_data() QTest::newRow("winter4") << QDateTime(QDate(6000, 2, 29), utcTime, Qt::UTC) << QDateTime(QDate(6000, 2, 29), localStandardTime, Qt::LocalTime); + // Test mktime boundaries (1970 - 2038) and adjustDate(). + QTest::newRow("1969/12/31 23:00 UTC") + << QDateTime(QDate(1969, 12, 31), QTime(23, 0, 0), Qt::UTC) + << QDateTime(QDate(1970, 1, 1), QTime(0, 0, 0), Qt::LocalTime); + QTest::newRow("2037/12/31 23:00 UTC") + << QDateTime(QDate(2037, 12, 31), QTime(23, 0, 0), Qt::UTC) + << QDateTime(QDate(2038, 1, 1), QTime(0, 0, 0), Qt::LocalTime); + + QTest::newRow("-271821/4/20 00:00 UTC (JavaScript min date, start of day)") + << QDateTime(QDate(-271821, 4, 20), QTime(0, 0, 0), Qt::UTC) + << QDateTime(QDate(-271821, 4, 20), QTime(1, 0, 0), Qt::LocalTime); + QTest::newRow("-271821/4/20 23:00 UTC (JavaScript min date, end of day)") + << QDateTime(QDate(-271821, 4, 20), QTime(23, 0, 0), Qt::UTC) + << QDateTime(QDate(-271821, 4, 21), QTime(0, 0, 0), Qt::LocalTime); + + QTest::newRow("QDate min") + << QDateTime(QDate::fromJulianDay(minJd()), QTime(0, 0, 0), Qt::UTC) + << QDateTime(QDate::fromJulianDay(minJd()), QTime(1, 0, 0), Qt::LocalTime); + + QTest::newRow("QDate max") + << QDateTime(QDate::fromJulianDay(maxJd()), QTime(22, 59, 59), Qt::UTC) + << QDateTime(QDate::fromJulianDay(maxJd()), QTime(23, 59, 59), Qt::LocalTime); + if (europeanTimeZone) { QTest::newRow("summer1") << QDateTime(QDate(2004, 6, 30), utcTime, Qt::UTC) << QDateTime(QDate(2004, 6, 30), localDaylightTime, Qt::LocalTime); @@ -835,6 +871,14 @@ void tst_QDateTime::toTimeSpec_data() #endif QTest::newRow("summer3") << QDateTime(QDate(4000, 6, 30), utcTime, Qt::UTC) << QDateTime(QDate(4000, 6, 30), localDaylightTime, Qt::LocalTime); + + QTest::newRow("275760/9/23 00:00 UTC (JavaScript max date, start of day)") + << QDateTime(QDate(275760, 9, 23), QTime(0, 0, 0), Qt::UTC) + << QDateTime(QDate(275760, 9, 23), QTime(2, 0, 0), Qt::LocalTime); + + QTest::newRow("275760/9/23 22:00 UTC (JavaScript max date, end of day)") + << QDateTime(QDate(275760, 9, 23), QTime(22, 0, 0), Qt::UTC) + << QDateTime(QDate(275760, 9, 24), QTime(0, 0, 0), Qt::LocalTime); } QTest::newRow("msec") << QDateTime(QDate(4000, 6, 30), utcTime.addMSecs(1), Qt::UTC) diff --git a/tests/auto/corelib/tools/qhash/tst_qhash.cpp b/tests/auto/corelib/tools/qhash/tst_qhash.cpp index 6df84e6363..903a4e1012 100644 --- a/tests/auto/corelib/tools/qhash/tst_qhash.cpp +++ b/tests/auto/corelib/tools/qhash/tst_qhash.cpp @@ -74,6 +74,7 @@ private slots: void const_shared_null(); void twoArguments_qHash(); + void initializerList(); }; struct Foo { @@ -1300,5 +1301,34 @@ void tst_QHash::twoArguments_qHash() QCOMPARE(wrongqHashOverload, 0); } +void tst_QHash::initializerList() +{ +#ifdef Q_COMPILER_INITIALIZER_LISTS + QHash<int, QString> hash{{1, "hello"}, {2, "initializer_list"}}; + QCOMPARE(hash.count(), 2); + QVERIFY(hash[1] == "hello"); + QVERIFY(hash[2] == "initializer_list"); + + QMultiHash<QString, int> multiHash{{"il", 1}, {"il", 2}, {"il", 3}}; + QCOMPARE(multiHash.count(), 3); + QList<int> values = multiHash.values("il"); + QCOMPARE(values.count(), 3); + + QHash<int, int> emptyHash{}; + QVERIFY(emptyHash.isEmpty()); + + QHash<int, char> emptyPairs{{}, {}}; + QVERIFY(!emptyPairs.isEmpty()); + + QMultiHash<QString, double> emptyMultiHash{}; + QVERIFY(emptyMultiHash.isEmpty()); + + QMultiHash<int, float> emptyPairs2{{}, {}}; + QVERIFY(!emptyPairs2.isEmpty()); +#else + QSKIP("Compiler doesn't support initializer lists"); +#endif +} + QTEST_APPLESS_MAIN(tst_QHash) #include "tst_qhash.moc" diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp index d58d207546..8fbe438760 100644 --- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp +++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp @@ -42,7 +42,7 @@ #include <QtTest/QtTest> #include <math.h> -#include <qglobal.h> +#include <qdebug.h> #include <qdir.h> #include <qfileinfo.h> #include <QScopedArrayPointer> @@ -712,6 +712,7 @@ void tst_QLocale::double_conversion() QFETCH(QString, num_str); QFETCH(bool, good); QFETCH(double, num); + QStringRef num_strRef = num_str.leftRef(-1); QLocale locale(locale_name); QCOMPARE(locale.name(), locale_name); @@ -726,6 +727,16 @@ void tst_QLocale::double_conversion() diff = -diff; QVERIFY(diff <= MY_DOUBLE_EPSILON); } + + d = locale.toDouble(num_strRef, &ok); + QCOMPARE(ok, good); + + if (ok) { + double diff = d - num; + if (diff < 0) + diff = -diff; + QVERIFY(diff <= MY_DOUBLE_EPSILON); + } } void tst_QLocale::long_long_conversion_data() @@ -787,6 +798,7 @@ void tst_QLocale::long_long_conversion() QFETCH(QString, num_str); QFETCH(bool, good); QFETCH(qlonglong, num); + QStringRef num_strRef = num_str.leftRef(-1); QLocale locale(locale_name); QCOMPARE(locale.name(), locale_name); @@ -795,9 +807,14 @@ void tst_QLocale::long_long_conversion() qlonglong l = locale.toLongLong(num_str, &ok); QCOMPARE(ok, good); - if (ok) { + if (ok) + QCOMPARE(l, num); + + l = locale.toLongLong(num_strRef, &ok); + QCOMPARE(ok, good); + + if (ok) QCOMPARE(l, num); - } } void tst_QLocale::long_long_conversion_extra() @@ -1281,7 +1298,7 @@ static QString getWinLocaleInfo(LCTYPE type) int cnt = GetLocaleInfo(id, type, 0, 0) * 2; if (cnt == 0) { - qWarning("QLocale: empty windows locale info (%d)", type); + qWarning().nospace() << "QLocale: empty windows locale info (" << type << ')'; return QString(); } cnt /= sizeof(wchar_t); @@ -1289,7 +1306,7 @@ static QString getWinLocaleInfo(LCTYPE type) cnt = GetLocaleInfo(id, type, buf.data(), cnt); if (cnt == 0) { - qWarning("QLocale: empty windows locale info (%d)", type); + qWarning().nospace() << "QLocale: empty windows locale info (" << type << ')'; return QString(); } return QString::fromWCharArray(buf.data()); diff --git a/tests/auto/corelib/tools/qmap/tst_qmap.cpp b/tests/auto/corelib/tools/qmap/tst_qmap.cpp index 5069b805bf..801656e1c3 100644 --- a/tests/auto/corelib/tools/qmap/tst_qmap.cpp +++ b/tests/auto/corelib/tools/qmap/tst_qmap.cpp @@ -84,6 +84,7 @@ private slots: void insert(); void checkMostLeftNode(); + void initializerList(); }; typedef QMap<QString, QString> StringMap; @@ -1129,5 +1130,34 @@ void tst_QMap::checkMostLeftNode() sanityCheckTree(map, __LINE__); } +void tst_QMap::initializerList() +{ +#ifdef Q_COMPILER_INITIALIZER_LISTS + QMap<int, QString> map{{1, "hello"}, {2, "initializer_list"}}; + QCOMPARE(map.count(), 2); + QVERIFY(map[1] == "hello"); + QVERIFY(map[2] == "initializer_list"); + + QMultiMap<QString, int> multiMap{{"il", 1}, {"il", 2}, {"il", 3}}; + QCOMPARE(multiMap.count(), 3); + QList<int> values = multiMap.values("il"); + QCOMPARE(values.count(), 3); + + QMap<int, int> emptyMap{}; + QVERIFY(emptyMap.isEmpty()); + + QMap<char, char> emptyPairs{{}, {}}; + QVERIFY(!emptyPairs.isEmpty()); + + QMultiMap<double, double> emptyMultiMap{}; + QVERIFY(emptyMultiMap.isEmpty()); + + QMultiMap<float, float> emptyPairs2{{}, {}}; + QVERIFY(!emptyPairs2.isEmpty()); +#else + QSKIP("Compiler doesn't support initializer lists"); +#endif +} + QTEST_APPLESS_MAIN(tst_QMap) #include "tst_qmap.moc" diff --git a/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp b/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp index 9700f91128..80311079d4 100644 --- a/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp +++ b/tests/auto/corelib/tools/qmargins/tst_qmargins.cpp @@ -50,6 +50,7 @@ class tst_QMargins : public QObject private slots: void getSetCheck(); void dataStreamCheck(); + void operators(); }; // Testing get/set functions @@ -75,6 +76,49 @@ void tst_QMargins::getSetCheck() QCOMPARE(margins, QMargins(5, 0, 5, 0)); } +void tst_QMargins::operators() +{ + const QMargins m1(12, 14, 16, 18); + const QMargins m2(2, 3, 4, 5); + + const QMargins added = m1 + m2; + QCOMPARE(added, QMargins(14, 17, 20, 23)); + QMargins a = m1; + a += m2; + QCOMPARE(a, added); + + const QMargins subtracted = m1 - m2; + QCOMPARE(subtracted, QMargins(10, 11, 12, 13)); + a = m1; + a -= m2; + QCOMPARE(a, subtracted); + + const QMargins doubled = m1 * 2; + QCOMPARE(doubled, QMargins(24, 28, 32, 36)); + QCOMPARE(2 * m1, doubled); + QCOMPARE(qreal(2) * m1, doubled); + QCOMPARE(m1 * qreal(2), doubled); + + a = m1; + a *= 2; + QCOMPARE(a, doubled); + a = m1; + a *= qreal(2); + QCOMPARE(a, doubled); + + const QMargins halved = m1 / 2; + QCOMPARE(halved, QMargins(6, 7, 8, 9)); + + a = m1; + a /= 2; + QCOMPARE(a, halved); + a = m1; + a /= qreal(2); + QCOMPARE(a, halved); + + QCOMPARE(m1 + (-m1), QMargins()); +} + // Testing QDataStream operators void tst_QMargins::dataStreamCheck() { diff --git a/tests/auto/corelib/tools/qmessageauthenticationcode/.gitignore b/tests/auto/corelib/tools/qmessageauthenticationcode/.gitignore new file mode 100644 index 0000000000..bfd53f437b --- /dev/null +++ b/tests/auto/corelib/tools/qmessageauthenticationcode/.gitignore @@ -0,0 +1 @@ +tst_qmessageauthenticationcode diff --git a/tests/auto/corelib/tools/qmessageauthenticationcode/qmessageauthenticationcode.pro b/tests/auto/corelib/tools/qmessageauthenticationcode/qmessageauthenticationcode.pro new file mode 100644 index 0000000000..1ea23915b7 --- /dev/null +++ b/tests/auto/corelib/tools/qmessageauthenticationcode/qmessageauthenticationcode.pro @@ -0,0 +1,7 @@ +CONFIG += testcase parallel_test +TARGET = tst_qmessageauthenticationcode +QT = core testlib +SOURCES = tst_qmessageauthenticationcode.cpp + +TESTDATA += data/* +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/tools/qmessageauthenticationcode/tst_qmessageauthenticationcode.cpp b/tests/auto/corelib/tools/qmessageauthenticationcode/tst_qmessageauthenticationcode.cpp new file mode 100644 index 0000000000..0e243988e2 --- /dev/null +++ b/tests/auto/corelib/tools/qmessageauthenticationcode/tst_qmessageauthenticationcode.cpp @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Ruslan Nigmatullin <euroelessar@yandex.ru> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtCore/QCoreApplication> +#include <QtTest/QtTest> + +class tst_QMessageAuthenticationCode : public QObject +{ + Q_OBJECT +private slots: + void result_data(); + void result(); + void result_incremental_data(); + void result_incremental(); +}; + +Q_DECLARE_METATYPE(QCryptographicHash::Algorithm) + +void tst_QMessageAuthenticationCode::result_data() +{ + QTest::addColumn<QCryptographicHash::Algorithm>("algo"); + QTest::addColumn<QByteArray>("key"); + QTest::addColumn<QByteArray>("message"); + QTest::addColumn<QByteArray>("code"); + + // Empty values + QTest::newRow("md5-empty") << QCryptographicHash::Md5 + << QByteArray() + << QByteArray() + << QByteArray::fromHex("74e6f7298a9c2d168935f58c001bad88"); + QTest::newRow("sha1-empty") << QCryptographicHash::Sha1 + << QByteArray() + << QByteArray() + << QByteArray::fromHex("fbdb1d1b18aa6c08324b7d64b71fb76370690e1d"); + QTest::newRow("sha256-empty") << QCryptographicHash::Sha256 + << QByteArray() + << QByteArray() + << QByteArray::fromHex("b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad"); + + // Some not-empty + QTest::newRow("md5") << QCryptographicHash::Md5 + << QByteArray("key") + << QByteArray("The quick brown fox jumps over the lazy dog") + << QByteArray::fromHex("80070713463e7749b90c2dc24911e275"); + QTest::newRow("sha1") << QCryptographicHash::Sha1 + << QByteArray("key") + << QByteArray("The quick brown fox jumps over the lazy dog") + << QByteArray::fromHex("de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"); + QTest::newRow("sha256") << QCryptographicHash::Sha256 + << QByteArray("key") + << QByteArray("The quick brown fox jumps over the lazy dog") + << QByteArray::fromHex("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8"); + + // Some from rfc-2104 + QTest::newRow("rfc-md5-1") << QCryptographicHash::Md5 + << QByteArray::fromHex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b") + << QByteArray("Hi There") + << QByteArray::fromHex("9294727a3638bb1c13f48ef8158bfc9d"); + QTest::newRow("rfc-md5-2") << QCryptographicHash::Md5 + << QByteArray("Jefe") + << QByteArray("what do ya want for nothing?") + << QByteArray::fromHex("750c783e6ab0b503eaa86e310a5db738"); + QTest::newRow("rfc-md5-3") << QCryptographicHash::Md5 + << QByteArray::fromHex("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") + << QByteArray(50, 0xdd) + << QByteArray::fromHex("56be34521d144c88dbb8c733f0e8b3f6"); +} + +void tst_QMessageAuthenticationCode::result() +{ + QFETCH(QCryptographicHash::Algorithm, algo); + QFETCH(QByteArray, key); + QFETCH(QByteArray, message); + QFETCH(QByteArray, code); + + QMessageAuthenticationCode mac(algo); + mac.setKey(key); + mac.addData(message); + QByteArray result = mac.result(); + + QCOMPARE(result, code); +} + +void tst_QMessageAuthenticationCode::result_incremental_data() +{ + result_data(); +} + +void tst_QMessageAuthenticationCode::result_incremental() +{ + QFETCH(QCryptographicHash::Algorithm, algo); + QFETCH(QByteArray, key); + QFETCH(QByteArray, message); + QFETCH(QByteArray, code); + + int index = message.length() / 2; + QByteArray leftPart(message.mid(0, index)); + QByteArray rightPart(message.mid(index)); + + QCOMPARE(leftPart + rightPart, message); + + QMessageAuthenticationCode mac(algo); + mac.setKey(key); + mac.addData(leftPart); + mac.addData(rightPart); + QByteArray result = mac.result(); + + QCOMPARE(result, code); +} + +QTEST_MAIN(tst_QMessageAuthenticationCode) +#include "tst_qmessageauthenticationcode.moc" diff --git a/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp b/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp index 924cac292e..3231469261 100644 --- a/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp +++ b/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp @@ -70,6 +70,9 @@ private slots: void operator_divide_data(); void operator_divide(); + void dotProduct_data(); + void dotProduct(); + void operator_unary_plus_data(); void operator_unary_plus(); @@ -271,6 +274,28 @@ void tst_QPoint::operator_divide() QCOMPARE(point, expected); } +void tst_QPoint::dotProduct_data() +{ + QTest::addColumn<QPoint>("point1"); + QTest::addColumn<QPoint>("point2"); + QTest::addColumn<int>("expected"); + + QTest::newRow("(0, 0) dot (0, 0)") << QPoint(0, 0) << QPoint(0, 0)<< 0; + QTest::newRow("(10, 0) dot (0, 10)") << QPoint(10, 0) << QPoint(0, 10) << 0; + QTest::newRow("(0, 10) dot (10, 0)") << QPoint(0, 10) << QPoint(10, 0) << 0; + QTest::newRow("(10, 20) dot (-10, -20)") << QPoint(10, 20) << QPoint(-10, -20) << -500; + QTest::newRow("(-10, -20) dot (10, 20)") << QPoint(-10, -20) << QPoint(10, 20) << -500; +} + +void tst_QPoint::dotProduct() +{ + QFETCH(QPoint, point1); + QFETCH(QPoint, point2); + QFETCH(int, expected); + + QCOMPARE(QPoint::dotProduct(point1, point2), expected); +} + void tst_QPoint::operator_unary_plus_data() { operator_unary_minus_data(); diff --git a/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp b/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp index 0f2e74e68e..fc79b40a18 100644 --- a/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp +++ b/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp @@ -75,6 +75,9 @@ private slots: void operator_divide(); void division(); + void dotProduct_data(); + void dotProduct(); + void operator_unary_plus_data(); void operator_unary_plus(); @@ -290,6 +293,29 @@ void tst_QPointF::division() } } +void tst_QPointF::dotProduct_data() +{ + QTest::addColumn<QPointF>("point1"); + QTest::addColumn<QPointF>("point2"); + QTest::addColumn<qreal>("expected"); + + QTest::newRow("(0, 0) dot (0, 0)") << QPointF(0, 0) << QPointF(0, 0) << qreal(0); + QTest::newRow("(10, 0) dot (0, 10)") << QPointF(10, 0) << QPointF(0, 10)<< qreal(0); + QTest::newRow("(0, 10) dot (10, 0)") << QPointF(0, 10) << QPointF(10, 0) << qreal(0); + QTest::newRow("(10, 20) dot (-10, -20)") << QPointF(10, 20) << QPointF(-10, -20) << qreal(-500); + QTest::newRow("(10.1, 20.2) dot (-10.1, -20.2)") << QPointF(10.1, 20.2) << QPointF(-10.1, -20.2) << qreal(-510.05); + QTest::newRow("(-10.1, -20.2) dot (10.1, 20.2)") << QPointF(-10.1, -20.2) << QPointF(10.1, 20.2) << qreal(-510.05); +} + +void tst_QPointF::dotProduct() +{ + QFETCH(QPointF, point1); + QFETCH(QPointF, point2); + QFETCH(qreal, expected); + + QCOMPARE(QPointF::dotProduct(point1, point2), expected); +} + void tst_QPointF::operator_unary_plus_data() { operator_unary_minus_data(); diff --git a/tests/auto/corelib/tools/qrect/tst_qrect.cpp b/tests/auto/corelib/tools/qrect/tst_qrect.cpp index b3fc8b0759..1b11673bd1 100644 --- a/tests/auto/corelib/tools/qrect/tst_qrect.cpp +++ b/tests/auto/corelib/tools/qrect/tst_qrect.cpp @@ -41,6 +41,7 @@ #include <QtTest/QtTest> #include <qrect.h> +#include <qmargins.h> #include <limits.h> #include <qdebug.h> @@ -133,6 +134,7 @@ private slots: void newMoveTopLeft(); void newMoveBottomRight_data(); void newMoveBottomRight(); + void margins(); void translate_data(); void translate(); @@ -3484,6 +3486,25 @@ void tst_QRect::newMoveBottomRight() QCOMPARE(r,nr); } +void tst_QRect::margins() +{ + const QRect rectangle = QRect(QPoint(10, 10), QSize(50 ,50)); + const QMargins margins = QMargins(2, 3, 4, 5); + + const QRect added = rectangle + margins; + QCOMPARE(added, QRect(QPoint(8, 7), QSize(56, 58))); + QCOMPARE(added, margins + rectangle); + QCOMPARE(added, rectangle.marginsAdded(margins)); + + QRect a = rectangle; + a += margins; + QCOMPARE(added, a); + + a = rectangle; + a -= margins; + QCOMPARE(a, QRect(QPoint(12, 13), QSize(44, 42))); + QCOMPARE(a, rectangle.marginsRemoved(margins)); +} void tst_QRect::translate_data() { diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp index 7073805db4..909725f4b8 100644 --- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp +++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>. +** Copyright (C) 2013 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. @@ -126,8 +127,6 @@ bool operator!=(const Match &m, const QRegularExpressionMatch &rem) bool operator==(const QRegularExpressionMatchIterator &iterator, const QList<Match> &expectedMatchList) { QRegularExpressionMatchIterator i = iterator; - if (i.isValid() != (!expectedMatchList.isEmpty())) - return false; foreach (const Match &expectedMatch, expectedMatchList) { @@ -293,6 +292,31 @@ void tst_QRegularExpression::provideRegularExpressions() | QRegularExpression::InvertedGreedinessOption); } +void tst_QRegularExpression::defaultConstructors() +{ + QRegularExpression re; + QCOMPARE(re.pattern(), QString()); + QCOMPARE(re.patternOptions(), QRegularExpression::NoPatternOption); + + QRegularExpressionMatch match; + QCOMPARE(match.regularExpression(), QRegularExpression()); + QCOMPARE(match.regularExpression(), re); + QCOMPARE(match.matchType(), QRegularExpression::NoMatch); + QCOMPARE(match.matchOptions(), QRegularExpression::NoMatchOption); + QCOMPARE(match.hasMatch(), false); + QCOMPARE(match.hasPartialMatch(), false); + QCOMPARE(match.isValid(), true); + QCOMPARE(match.lastCapturedIndex(), -1); + + QRegularExpressionMatchIterator iterator; + QCOMPARE(iterator.regularExpression(), QRegularExpression()); + QCOMPARE(iterator.regularExpression(), re); + QCOMPARE(iterator.matchType(), QRegularExpression::NoMatch); + QCOMPARE(iterator.matchOptions(), QRegularExpression::NoMatchOption); + QCOMPARE(iterator.isValid(), true); + QCOMPARE(iterator.hasNext(), false); +} + void tst_QRegularExpression::gettersSetters_data() { provideRegularExpressions(); @@ -693,12 +717,31 @@ void tst_QRegularExpression::normalMatch() QFETCH(QRegularExpression::MatchOptions, matchOptions); QFETCH(Match, match); - QRegularExpressionMatch m = regexp.match(subject, offset, QRegularExpression::NormalMatch, matchOptions); - consistencyCheck(m); - QVERIFY(m == match); + { + QRegularExpressionMatch m = regexp.match(subject, offset, QRegularExpression::NormalMatch, matchOptions); + consistencyCheck(m); + QVERIFY(m == match); + QCOMPARE(m.regularExpression(), regexp); + QCOMPARE(m.matchType(), QRegularExpression::NormalMatch); + QCOMPARE(m.matchOptions(), matchOptions); + } + { + // ignore the expected results provided by the match object -- + // we'll never get any result when testing the NoMatch type. + // Just check the validity of the match here. + Match realMatch; + realMatch.clear(); + realMatch.isValid = match.isValid; + + QRegularExpressionMatch m = regexp.match(subject, offset, QRegularExpression::NoMatch, matchOptions); + consistencyCheck(m); + QVERIFY(m == realMatch); + QCOMPARE(m.regularExpression(), regexp); + QCOMPARE(m.matchType(), QRegularExpression::NoMatch); + QCOMPARE(m.matchOptions(), matchOptions); + } } - void tst_QRegularExpression::partialMatch_data() { QTest::addColumn<QRegularExpression>("regexp"); @@ -952,9 +995,29 @@ void tst_QRegularExpression::partialMatch() QFETCH(QRegularExpression::MatchOptions, matchOptions); QFETCH(Match, match); - QRegularExpressionMatch m = regexp.match(subject, offset, matchType, matchOptions); - consistencyCheck(m); - QVERIFY(m == match); + { + QRegularExpressionMatch m = regexp.match(subject, offset, matchType, matchOptions); + consistencyCheck(m); + QVERIFY(m == match); + QCOMPARE(m.regularExpression(), regexp); + QCOMPARE(m.matchType(), matchType); + QCOMPARE(m.matchOptions(), matchOptions); + } + { + // ignore the expected results provided by the match object -- + // we'll never get any result when testing the NoMatch type. + // Just check the validity of the match here. + Match realMatch; + realMatch.clear(); + realMatch.isValid = match.isValid; + + QRegularExpressionMatch m = regexp.match(subject, offset, QRegularExpression::NoMatch, matchOptions); + consistencyCheck(m); + QVERIFY(m == realMatch); + QCOMPARE(m.regularExpression(), regexp); + QCOMPARE(m.matchType(), QRegularExpression::NoMatch); + QCOMPARE(m.matchOptions(), matchOptions); + } } void tst_QRegularExpression::globalMatch_data() @@ -1223,10 +1286,28 @@ void tst_QRegularExpression::globalMatch() QFETCH(QRegularExpression::MatchType, matchType); QFETCH(QRegularExpression::MatchOptions, matchOptions); QFETCH(QList<Match>, matchList); + { + QRegularExpressionMatchIterator iterator = regexp.globalMatch(subject, offset, matchType, matchOptions); + consistencyCheck(iterator); + QVERIFY(iterator == matchList); + QCOMPARE(iterator.regularExpression(), regexp); + QCOMPARE(iterator.matchType(), matchType); + QCOMPARE(iterator.matchOptions(), matchOptions); + } + { + // ignore the expected results provided by the match object -- + // we'll never get any result when testing the NoMatch type. + // Just check the validity of the match here. + QList<Match> realMatchList; + + QRegularExpressionMatchIterator iterator = regexp.globalMatch(subject, offset, QRegularExpression::NoMatch, matchOptions); + consistencyCheck(iterator); + QVERIFY(iterator == realMatchList); + QCOMPARE(iterator.regularExpression(), regexp); + QCOMPARE(iterator.matchType(), QRegularExpression::NoMatch); + QCOMPARE(iterator.matchOptions(), matchOptions); + } - QRegularExpressionMatchIterator iterator = regexp.globalMatch(subject, offset, matchType, matchOptions); - consistencyCheck(iterator); - QVERIFY(iterator == matchList); } void tst_QRegularExpression::serialize_data() @@ -1338,6 +1419,86 @@ void tst_QRegularExpression::captureCount() QCOMPARE(re.captureCount(), -1); } +// the comma in the template breaks QFETCH... +typedef QMultiHash<QString, int> StringToIntMap; +Q_DECLARE_METATYPE(StringToIntMap) + +void tst_QRegularExpression::captureNames_data() +{ + QTest::addColumn<QString>("pattern"); + QTest::addColumn<StringToIntMap>("namedCapturesIndexMap"); + StringToIntMap map; + + QTest::newRow("captureNames01") << "a pattern" << map; + QTest::newRow("captureNames02") << "a.*pattern" << map; + QTest::newRow("captureNames03") << "(a) pattern" << map; + QTest::newRow("captureNames04") << "(a).*(pattern)" << map; + + map.clear(); + map.replace("named", 1); + QTest::newRow("captureNames05") << "a.*(?<named>pattern)" << map; + + map.clear(); + map.replace("named", 2); + QTest::newRow("captureNames06") << "(a).*(?<named>pattern)" << map; + + map.clear(); + map.replace("name1", 1); + map.replace("name2", 2); + QTest::newRow("captureNames07") << "(?<name1>a).*(?<name2>pattern)" << map; + + map.clear(); + map.replace("name1", 2); + map.replace("name2", 1); + QTest::newRow("captureNames08") << "(?<name2>a).*(?<name1>pattern)" << map; + + map.clear(); + map.replace("date", 1); + map.replace("month", 2); + map.replace("year", 3); + QTest::newRow("captureNames09") << "^(?<date>\\d\\d)/(?<month>\\d\\d)/(?<year>\\d\\d\\d\\d)$" << map; + + map.clear(); + map.replace("date", 2); + map.replace("month", 1); + map.replace("year", 3); + QTest::newRow("captureNames10") << "^(?<month>\\d\\d)/(?<date>\\d\\d)/(?<year>\\d\\d\\d\\d)$" << map; + + map.clear(); + map.replace("noun", 2); + QTest::newRow("captureNames11") << "(a)(?|(?<noun>b)|(?<noun>c))(d)" << map; + + map.clear(); + QTest::newRow("captureNames_invalid01") << "(.*" << map; + QTest::newRow("captureNames_invalid02") << "\\" << map; + QTest::newRow("captureNames_invalid03") << "(?<noun)" << map; + QTest::newRow("captureNames_invalid04") << "(?|(?<noun1>a)|(?<noun2>b))" << map; +} + +void tst_QRegularExpression::captureNames() +{ + QFETCH(QString, pattern); + QFETCH(StringToIntMap, namedCapturesIndexMap); + + const QRegularExpression re(pattern); + QStringList namedCaptureGroups = re.namedCaptureGroups(); + int namedCaptureGroupsCount = namedCaptureGroups.size(); + + QCOMPARE(namedCaptureGroupsCount, re.captureCount() + 1); + + for (int i = 0; i < namedCaptureGroupsCount; ++i) { + const QString &name = namedCaptureGroups.at(i); + + if (name.isEmpty()) { + QVERIFY(!namedCapturesIndexMap.contains(name)); + } else { + QVERIFY(namedCapturesIndexMap.contains(name)); + QCOMPARE(i, namedCapturesIndexMap.value(name)); + } + } + +} + void tst_QRegularExpression::pcreJitStackUsage_data() { QTest::addColumn<QString>("pattern"); @@ -1389,3 +1550,35 @@ void tst_QRegularExpression::regularExpressionMatch() QTest::ignoreMessage(QtWarningMsg, "QRegularExpressionMatch::captured: empty capturing group name passed"); QCOMPARE(match.captured(QString()).isNull(), true); } + +void tst_QRegularExpression::JOptionUsage_data() +{ + QTest::addColumn<QString>("pattern"); + QTest::addColumn<bool>("isValid"); + QTest::addColumn<bool>("JOptionUsed"); + + QTest::newRow("joption-notused-01") << "a.*b" << true << false; + QTest::newRow("joption-notused-02") << "^a(b)(c)$" << true << false; + QTest::newRow("joption-notused-03") << "a(b)(?<c>d)|e" << true << false; + QTest::newRow("joption-notused-04") << "(?<a>.)(?<a>.)" << false << false; + + QTest::newRow("joption-used-01") << "(?J)a.*b" << true << true; + QTest::newRow("joption-used-02") << "(?-J)a.*b" << true << true; + QTest::newRow("joption-used-03") << "(?J)(?<a>.)(?<a>.)" << true << true; + QTest::newRow("joption-used-04") << "(?-J)(?<a>.)(?<a>.)" << false << true; + +} + +void tst_QRegularExpression::JOptionUsage() +{ + QFETCH(QString, pattern); + QFETCH(bool, isValid); + QFETCH(bool, JOptionUsed); + + const QString warningMessage = QStringLiteral("QRegularExpressionPrivate::getPatternInfo(): the pattern '%1'\n is using the (?J) option; duplicate capturing group names are not supported by Qt"); + + QRegularExpression re(pattern); + if (isValid && JOptionUsed) + QTest::ignoreMessage(QtWarningMsg, qPrintable(warningMessage.arg(pattern))); + QCOMPARE(re.isValid(), isValid); +} diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h index d6f9312411..0f62570114 100644 --- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h +++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h @@ -51,6 +51,7 @@ class tst_QRegularExpression : public QObject Q_OBJECT private slots: + void defaultConstructors(); void gettersSetters_data(); void gettersSetters(); void escape_data(); @@ -71,10 +72,14 @@ private slots: void operatoreq(); void captureCount_data(); void captureCount(); + void captureNames_data(); + void captureNames(); void pcreJitStackUsage_data(); void pcreJitStackUsage(); void regularExpressionMatch_data(); void regularExpressionMatch(); + void JOptionUsage_data(); + void JOptionUsage(); private: void provideRegularExpressions(); diff --git a/tests/auto/corelib/tools/qset/tst_qset.cpp b/tests/auto/corelib/tools/qset/tst_qset.cpp index a3232d05c3..eaa1c018ba 100644 --- a/tests/auto/corelib/tools/qset/tst_qset.cpp +++ b/tests/auto/corelib/tools/qset/tst_qset.cpp @@ -79,6 +79,7 @@ private slots: void javaIterator(); void javaMutableIterator(); void makeSureTheComfortFunctionsCompile(); + void initializerList(); }; void tst_QSet::operator_eq() @@ -918,6 +919,27 @@ void tst_QSet::makeSureTheComfortFunctionsCompile() set1 = set2 - set3; } +void tst_QSet::initializerList() +{ +#ifdef Q_COMPILER_INITIALIZER_LISTS + QSet<int> set{1, 2, 3, 4, 5}; + QCOMPARE(set.count(), 5); + QVERIFY(set.contains(1)); + QVERIFY(set.contains(2)); + QVERIFY(set.contains(3)); + QVERIFY(set.contains(4)); + QVERIFY(set.contains(5)); + + QSet<int> emptySet{}; + QVERIFY(emptySet.isEmpty()); + + QSet<int> set3{{}, {}, {}}; + QVERIFY(!set3.isEmpty()); +#else + QSKIP("Compiler doesn't support initializer lists"); +#endif +} + QTEST_APPLESS_MAIN(tst_QSet) #include "tst_qset.moc" diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp index 8e10b757c8..5b1a2cf076 100644 --- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp @@ -97,6 +97,7 @@ private slots: void lambdaCustomDeleter(); #endif void creating(); + void creatingVariadic(); void creatingQObject(); void mixTrackingPointerCode(); void reentrancyWhileDestructing(); @@ -176,6 +177,49 @@ public: int Data::generationCounter = 0; int Data::destructorCounter = 0; +struct NoDefaultConstructor1 +{ + int i; + NoDefaultConstructor1(int i) : i(i) {} + NoDefaultConstructor1(uint j) : i(j + 42) {} +}; + +struct NoDefaultConstructorRef1 +{ + int &i; + NoDefaultConstructorRef1(int &i) : i(i) {} +}; + +struct NoDefaultConstructor2 +{ + void *ptr; + int i; + NoDefaultConstructor2(void *ptr, int i) : ptr(ptr), i(i) {} +}; + +struct NoDefaultConstructorRef2 +{ + QString str; + int i; + NoDefaultConstructorRef2(QString &str, int i) : str(str), i(i) {} +}; + +struct NoDefaultConstructorConstRef2 +{ + QString str; + int i; + NoDefaultConstructorConstRef2(const QString &str, int i) : str(str), i(i) {} + NoDefaultConstructorConstRef2(const QByteArray &ba, int i = 42) : str(QString::fromLatin1(ba)), i(i) {} +}; + +#ifdef Q_COMPILER_RVALUE_REFS +struct NoDefaultConstructorRRef1 +{ + int &i; + NoDefaultConstructorRRef1(int &&i) : i(i) {} +}; +#endif + void tst_QSharedPointer::basics_data() { QTest::addColumn<bool>("isNull"); @@ -1436,6 +1480,82 @@ void tst_QSharedPointer::creating() safetyCheck(); } +void tst_QSharedPointer::creatingVariadic() +{ +#if !defined(Q_COMPILER_RVALUE_REFS) || !defined(Q_COMPILER_VARIADIC_TEMPLATES) + QSKIP("This compiler is not in C++11 mode or it doesn't support rvalue refs and variadic templates"); +#else + int i = 42; + + { + NoDefaultConstructor1(1); // control check + QSharedPointer<NoDefaultConstructor1> ptr = QSharedPointer<NoDefaultConstructor1>::create(1); + QCOMPARE(ptr->i, 1); + + NoDefaultConstructor1(0u); // control check + ptr = QSharedPointer<NoDefaultConstructor1>::create(0u); + QCOMPARE(ptr->i, 42); + + NoDefaultConstructor1 x(i); // control check + ptr = QSharedPointer<NoDefaultConstructor1>::create(i); + QCOMPARE(ptr->i, i); + } + { + NoDefaultConstructor2((void*)0, 1); // control check + QSharedPointer<NoDefaultConstructor2> ptr = QSharedPointer<NoDefaultConstructor2>::create((void*)0, 1); + QCOMPARE(ptr->i, 1); + QCOMPARE(ptr->ptr, (void*)0); + + int *null = 0; + NoDefaultConstructor2(null, 2); // control check + ptr = QSharedPointer<NoDefaultConstructor2>::create(null, 2); + QCOMPARE(ptr->i, 2); + QCOMPARE(ptr->ptr, (void*)0); + +#ifdef Q_COMPILER_NULLPTR + NoDefaultConstructor2(nullptr, 3); // control check + ptr = QSharedPointer<NoDefaultConstructor2>::create(nullptr, 3); + QCOMPARE(ptr->i, 3); + QCOMPARE(ptr->ptr, (void*)nullptr); +#endif + } + { + NoDefaultConstructorRef1 x(i); // control check + QSharedPointer<NoDefaultConstructorRef1> ptr = QSharedPointer<NoDefaultConstructorRef1>::create(i); + QCOMPARE(ptr->i, i); + QCOMPARE(&ptr->i, &i); + } + { + NoDefaultConstructorRRef1(1); // control check + QSharedPointer<NoDefaultConstructorRRef1> ptr = QSharedPointer<NoDefaultConstructorRRef1>::create(1); + QCOMPARE(ptr->i, 1); + + NoDefaultConstructorRRef1(std::move(i)); // control check + ptr = QSharedPointer<NoDefaultConstructorRRef1>::create(std::move(i)); + QCOMPARE(ptr->i, i); + } + { + QString text("Hello, World"); + NoDefaultConstructorRef2(text, 1); // control check + QSharedPointer<NoDefaultConstructorRef2> ptr = QSharedPointer<NoDefaultConstructorRef2>::create(text, 1); + QCOMPARE(ptr->str, text); + QCOMPARE(ptr->i, 1); + } + { + QSharedPointer<NoDefaultConstructorConstRef2> ptr; + NoDefaultConstructorConstRef2(QLatin1String("string"), 1); // control check + ptr = QSharedPointer<NoDefaultConstructorConstRef2>::create(QLatin1String("string"), 1); + QCOMPARE(ptr->str, QString("string")); + QCOMPARE(ptr->i, 1); + + NoDefaultConstructorConstRef2(QByteArray("bytearray")); // control check + ptr = QSharedPointer<NoDefaultConstructorConstRef2>::create(QByteArray("bytearray")); + QCOMPARE(ptr->str, QString("bytearray")); + QCOMPARE(ptr->i, 42); + } +#endif +} + void tst_QSharedPointer::creatingQObject() { { @@ -1876,7 +1996,7 @@ void tst_QSharedPointer::invalidConstructs() QByteArray body = code.toLatin1(); bool result = (test.*testFunction)(body); - if (qgetenv("QTEST_EXTERNAL_DEBUG").toInt() > 0) { + if (!result || qgetenv("QTEST_EXTERNAL_DEBUG").toInt() > 0) { qDebug("External test output:"); #ifdef Q_CC_MSVC // MSVC prints errors to stdout diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index 8e30a66d6f..aa61885a47 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -195,6 +195,8 @@ private slots: void stringRef_local8Bit(); void fromLatin1(); void fromAscii(); + void fromUcs4(); + void toUcs4(); void arg(); void number(); void arg_fillChar_data(); @@ -238,7 +240,7 @@ private slots: #ifdef QT_USE_ICU void toUpperLower_icu(); #endif -#if defined(QT_UNICODE_LITERAL) && (defined(Q_COMPILER_LAMBDA) || defined(Q_CC_GNU)) +#if !defined(QT_NO_UNICODE_LITERAL) && defined(Q_COMPILER_LAMBDA) void literals(); #endif void eightBitLiterals_data(); @@ -1003,10 +1005,12 @@ void tst_QString::sprintf() a.sprintf("%s%n%s", "hello", &n1, "goodbye"); QCOMPARE(n1, 5); QCOMPARE(a, QString("hellogoodbye")); +#ifndef Q_CC_MINGW // does not know %ll qlonglong n2; a.sprintf("%s%s%lln%s", "foo", "bar", &n2, "whiz"); QCOMPARE((int)n2, 6); QCOMPARE(a, QString("foobarwhiz")); +#endif } /* @@ -1425,6 +1429,55 @@ void tst_QString::contains() QVERIFY(a.contains(QRegularExpression("[FG][HI]"))); QVERIFY(a.contains(QRegularExpression("[G][HE]"))); + { + QRegularExpressionMatch match; + QVERIFY(!match.hasMatch()); + + QVERIFY(a.contains(QRegularExpression("[FG][HI]"), &match)); + QVERIFY(match.hasMatch()); + QCOMPARE(match.capturedStart(), 6); + QCOMPARE(match.capturedEnd(), 8); + QCOMPARE(match.captured(), QStringLiteral("GH")); + + QVERIFY(a.contains(QRegularExpression("[G][HE]"), &match)); + QVERIFY(match.hasMatch()); + QCOMPARE(match.capturedStart(), 6); + QCOMPARE(match.capturedEnd(), 8); + QCOMPARE(match.captured(), QStringLiteral("GH")); + + QVERIFY(a.contains(QRegularExpression("[f](.*)[FG]"), &match)); + QVERIFY(match.hasMatch()); + QCOMPARE(match.capturedStart(), 10); + QCOMPARE(match.capturedEnd(), 15); + QCOMPARE(match.captured(), QString("fGEFG")); + QCOMPARE(match.capturedStart(1), 11); + QCOMPARE(match.capturedEnd(1), 14); + QCOMPARE(match.captured(1), QStringLiteral("GEF")); + + QVERIFY(a.contains(QRegularExpression("[f](.*)[F]"), &match)); + QVERIFY(match.hasMatch()); + QCOMPARE(match.capturedStart(), 10); + QCOMPARE(match.capturedEnd(), 14); + QCOMPARE(match.captured(), QString("fGEF")); + QCOMPARE(match.capturedStart(1), 11); + QCOMPARE(match.capturedEnd(1), 13); + QCOMPARE(match.captured(1), QStringLiteral("GE")); + + QVERIFY(!a.contains(QRegularExpression("ZZZ"), &match)); + // doesn't match, but ensure match didn't change + QVERIFY(match.hasMatch()); + QCOMPARE(match.capturedStart(), 10); + QCOMPARE(match.capturedEnd(), 14); + QCOMPARE(match.captured(), QStringLiteral("fGEF")); + QCOMPARE(match.capturedStart(1), 11); + QCOMPARE(match.capturedEnd(1), 13); + QCOMPARE(match.captured(1), QStringLiteral("GE")); + + // don't crash with a null pointer + QVERIFY(a.contains(QRegularExpression("[FG][HI]"), 0)); + QVERIFY(!a.contains(QRegularExpression("ZZZ"), 0)); + } + CREATE_REF(QLatin1String("FG")); QVERIFY(a.contains(ref)); QVERIFY(a.contains(ref, Qt::CaseInsensitive)); @@ -3880,6 +3933,52 @@ void tst_QString::fromAscii() QVERIFY(a.size() == 5); } +void tst_QString::fromUcs4() +{ + QString s; + s = QString::fromUcs4( 0 ); + QVERIFY( s.isNull() ); + QCOMPARE( s.size(), 0 ); + s = QString::fromUcs4( 0, 0 ); + QVERIFY( s.isNull() ); + QCOMPARE( s.size(), 0 ); + s = QString::fromUcs4( 0, 5 ); + QVERIFY( s.isNull() ); + QCOMPARE( s.size(), 0 ); + + uint nil = '\0'; + s = QString::fromUcs4( &nil ); + QVERIFY( !s.isNull() ); + QCOMPARE( s.size(), 0 ); + s = QString::fromUcs4( &nil, 0 ); + QVERIFY( !s.isNull() ); + QCOMPARE( s.size(), 0 ); + + uint bmp = 'a'; + s = QString::fromUcs4( &bmp, 1 ); + QVERIFY( !s.isNull() ); + QCOMPARE( s.size(), 1 ); + + uint smp = 0x10000; + s = QString::fromUcs4( &smp, 1 ); + QVERIFY( !s.isNull() ); + QCOMPARE( s.size(), 2 ); +} + +void tst_QString::toUcs4() +{ + QString s; + QCOMPARE( s.toUcs4().size(), 0 ); + + QChar bmp = QLatin1Char('a'); + s = QString(&bmp, 1); + QCOMPARE( s.toUcs4().size(), 1 ); + + QChar smp[] = { QChar::highSurrogate(0x10000), QChar::lowSurrogate(0x10000) }; + s = QString(smp, 2); + QCOMPARE( s.toUcs4().size(), 1 ); +} + void tst_QString::arg() { /* @@ -5187,6 +5286,9 @@ void tst_QString::QCharRefDetaching() const void tst_QString::sprintfZU() const { +#ifdef Q_CC_MINGW + QSKIP("MinGW does not support '%zu'."); +#else { QString string; size_t s = 6; @@ -5215,6 +5317,7 @@ void tst_QString::sprintfZU() const string.sprintf("%zu %s\n", s, "foo"); QCOMPARE(string, QString::fromLatin1("6 foo\n")); } +#endif // !Q_CC_MINGW } void tst_QString::repeatedSignature() const @@ -5382,7 +5485,7 @@ void tst_QString::toUpperLower_icu() } #endif -#if defined(QT_UNICODE_LITERAL) && (defined(Q_COMPILER_LAMBDA) || defined(Q_CC_GNU)) +#if !defined(QT_NO_UNICODE_LITERAL) && defined(Q_COMPILER_LAMBDA) // Only tested on c++0x compliant compiler or gcc void tst_QString::literals() { diff --git a/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp b/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp index 66f40e05cb..1045d5929f 100644 --- a/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp +++ b/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp @@ -69,6 +69,25 @@ private slots: void compare_data(); void compare(); void operator_eqeq_nullstring(); + void toNum(); + void toDouble_data(); + void toDouble(); + void toFloat(); + void toLong_data(); + void toLong(); + void toULong_data(); + void toULong(); + void toLongLong(); + void toULongLong(); + void toUInt(); + void toInt(); + void toShort(); + void toUShort(); + void double_conversion_data(); + void double_conversion(); + void integer_conversion_data(); + void integer_conversion(); + void trimmed(); }; static QStringRef emptyRef() @@ -840,6 +859,941 @@ void tst_QStringRef::compare() } } +void tst_QStringRef::toNum() +{ +#define TEST_TO_INT(num, func, type) \ + a = #num; \ + b = a.leftRef(-1); \ + QCOMPARE(b.func(&ok), type(Q_INT64_C(num))); \ + QVERIFY2(ok, "Failed: num=" #num); + + QString a; + QStringRef b; + bool ok = false; + + TEST_TO_INT(0, toInt, int) + TEST_TO_INT(-1, toInt, int) + TEST_TO_INT(1, toInt, int) + TEST_TO_INT(2147483647, toInt, int) + TEST_TO_INT(-2147483648, toInt, int) + + TEST_TO_INT(0, toShort, short) + TEST_TO_INT(-1, toShort, short) + TEST_TO_INT(1, toShort, short) + TEST_TO_INT(32767, toShort, short) + TEST_TO_INT(-32768, toShort, short) + + TEST_TO_INT(0, toLong, long) + TEST_TO_INT(-1, toLong, long) + TEST_TO_INT(1, toLong, long) + TEST_TO_INT(2147483647, toLong, long) + TEST_TO_INT(-2147483648, toLong, long) + TEST_TO_INT(0, toLongLong, (long long)) + TEST_TO_INT(-1, toLongLong, (long long)) + TEST_TO_INT(1, toLongLong, (long long)) + TEST_TO_INT(9223372036854775807, toLongLong, (long long)) + TEST_TO_INT(-9223372036854775807, toLongLong, (long long)) + +#undef TEST_TO_INT + +#define TEST_TO_UINT(num, func, type) \ + a = #num; \ + b = a.leftRef(-1); \ + QCOMPARE(b.func(&ok), type(Q_UINT64_C(num))); \ + QVERIFY2(ok, "Failed: num=" #num); + + TEST_TO_UINT(0, toUInt, (unsigned int)) + TEST_TO_UINT(1, toUInt, (unsigned int)) + TEST_TO_UINT(4294967295, toUInt, (unsigned int)) + + TEST_TO_UINT(0, toUShort, (unsigned short)) + TEST_TO_UINT(1, toUShort, (unsigned short)) + TEST_TO_UINT(65535, toUShort, (unsigned short)) + + TEST_TO_UINT(0, toULong, (unsigned long)) + TEST_TO_UINT(1, toULong, (unsigned long)) + TEST_TO_UINT(4294967295, toULong, (unsigned long)) + + TEST_TO_UINT(0, toULongLong, (unsigned long long)) + TEST_TO_UINT(1, toULongLong, (unsigned long long)) + TEST_TO_UINT(18446744073709551615, toULongLong, (unsigned long long)) + +#undef TEST_TO_UINT + +#define TEST_BASE(str, base, num) \ + a = str; \ + b = a.leftRef(-1); \ + QCOMPARE(b.toInt(&ok,base), int(num)); \ + QVERIFY2(ok, "Failed: str=" #str " base= " #base " num=" #num ", func=toInt"); \ + QCOMPARE(b.toUInt(&ok, base), (unsigned int)(num)); \ + QVERIFY2(ok, "Failed: str=" #str " base= " #base " num=" #num ", func=toUInt"); \ + QCOMPARE(b.toShort(&ok, base), short(num)); \ + QVERIFY2(ok, "Failed: str=" #str " base= " #base " num=" #num ", func=toShort"); \ + QCOMPARE(b.toUShort(&ok, base), (unsigned short)(num)); \ + QVERIFY2(ok, "Failed: str=" #str " base= " #base " num=" #num ", func=toUShort"); \ + QCOMPARE(b.toLong(&ok, base), long(num)); \ + QVERIFY2(ok, "Failed: str=" #str " base= " #base " num=" #num ", func=toLong"); \ + QCOMPARE(b.toULong(&ok, base), (unsigned long)(num)); \ + QVERIFY2(ok, "Failed: str=" #str " base= " #base " num=" #num ", func=toULong"); \ + QCOMPARE(b.toLongLong(&ok, base), (long long)(num)); \ + QVERIFY2(ok, "Failed: str=" #str " base= " #base " num=" #num ", func=toLongLong"); \ + QCOMPARE(b.toULongLong(&ok, base), (unsigned long long)(num)); \ + QVERIFY2(ok, "Failed: str=" #str " base= " #base " num=" #num ", func=toULongLong"); + + TEST_BASE("FF", 16, 255) + TEST_BASE("0xFF", 16, 255) + TEST_BASE("77", 8, 63) + TEST_BASE("077", 8, 63) + + TEST_BASE("0xFF", 0, 255) + TEST_BASE("077", 0, 63) + TEST_BASE("255", 0, 255) + + TEST_BASE(" FF", 16, 255) + TEST_BASE(" 0xFF", 16, 255) + TEST_BASE(" 77", 8, 63) + TEST_BASE(" 077", 8, 63) + + TEST_BASE(" 0xFF", 0, 255) + TEST_BASE(" 077", 0, 63) + TEST_BASE(" 255", 0, 255) + + TEST_BASE("\tFF\t", 16, 255) + TEST_BASE("\t0xFF ", 16, 255) + TEST_BASE(" 77 ", 8, 63) + TEST_BASE("77 ", 8, 63) + +#undef TEST_BASE + +#define TEST_NEG_BASE(str, base, num) \ + a = str; \ + b = a.leftRef(-1); \ + QCOMPARE(b.toInt(&ok, base), int(num)); \ + QVERIFY2(ok, "Failed: str=" #str " base= "#base " num=" #num ", func=toInt"); \ + QCOMPARE(b.toShort(&ok,base), short(num)); \ + QVERIFY2(ok, "Failed: str=" #str " base= "#base " num=" #num ", func=toShort"); \ + QCOMPARE(b.toLong(&ok, base), long(num)); \ + QVERIFY2(ok, "Failed: str=" #str " base= "#base " num=" #num ", func=toLong"); \ + QCOMPARE(b.toLongLong(&ok, base), (long long)(num)); \ + QVERIFY2(ok, "Failed: str=" #str " base= "#base " num=" #num ", func=toLongLong"); + + TEST_NEG_BASE("-FE", 16, -254) + TEST_NEG_BASE("-0xFE", 16, -254) + TEST_NEG_BASE("-77", 8, -63) + TEST_NEG_BASE("-077", 8, -63) + + TEST_NEG_BASE("-0xFE", 0, -254) + TEST_NEG_BASE("-077", 0, -63) + TEST_NEG_BASE("-254", 0, -254) + +#undef TEST_NEG_BASE + +#define TEST_DOUBLE(num, str) \ + a = str; \ + b = a.leftRef(-1); \ + QCOMPARE(b.toDouble(&ok), num); \ + QVERIFY(ok); + + TEST_DOUBLE(1.2345, "1.2345") + TEST_DOUBLE(12.345, "1.2345e+01") + TEST_DOUBLE(12.345, "1.2345E+01") + TEST_DOUBLE(12345.6, "12345.6") + +#undef TEST_DOUBLE + +#define TEST_BAD(str, func) \ + a = str; \ + b = a.leftRef(-1); \ + b.func(&ok); \ + QVERIFY2(!ok, "Failed: str=" #str " func=" #func); + + TEST_BAD("32768", toShort) + TEST_BAD("-32769", toShort) + TEST_BAD("65536", toUShort) + TEST_BAD("2147483648", toInt) + TEST_BAD("-2147483649", toInt) + TEST_BAD("4294967296", toUInt) + if (sizeof(long) == 4) { + TEST_BAD("2147483648", toLong) + TEST_BAD("-2147483649", toLong) + TEST_BAD("4294967296", toULong) + } + TEST_BAD("9223372036854775808", toLongLong) + TEST_BAD("-9223372036854775809", toLongLong) + TEST_BAD("18446744073709551616", toULongLong) + TEST_BAD("-1", toUShort) + TEST_BAD("-1", toUInt) + TEST_BAD("-1", toULong) + TEST_BAD("-1", toULongLong) + +#undef TEST_BAD + +#define TEST_BAD_ALL(str) \ + a = str; \ + b = a.leftRef(-1); \ + b.toShort(&ok); \ + QVERIFY2(!ok, "Failed: str=" #str); \ + b.toUShort(&ok); \ + QVERIFY2(!ok, "Failed: str=" #str); \ + b.toInt(&ok); \ + QVERIFY2(!ok, "Failed: str=" #str); \ + b.toUInt(&ok); \ + QVERIFY2(!ok, "Failed: str=" #str); \ + b.toLong(&ok); \ + QVERIFY2(!ok, "Failed: str=" #str); \ + b.toULong(&ok); \ + QVERIFY2(!ok, "Failed: str=" #str); \ + b.toLongLong(&ok); \ + QVERIFY2(!ok, "Failed: str=" #str); \ + b.toULongLong(&ok); \ + QVERIFY2(!ok, "Failed: str=" #str); \ + b.toFloat(&ok); \ + QVERIFY2(!ok, "Failed: str=" #str); \ + b.toDouble(&ok); \ + QVERIFY2(!ok, "Failed: str=" #str); + + TEST_BAD_ALL((const char*)0); + TEST_BAD_ALL(""); + TEST_BAD_ALL(" "); + TEST_BAD_ALL("."); + TEST_BAD_ALL("-"); + TEST_BAD_ALL("hello"); + TEST_BAD_ALL("1.2.3"); + TEST_BAD_ALL("0x0x0x"); + TEST_BAD_ALL("123-^~<"); + TEST_BAD_ALL("123ThisIsNotANumber"); + +#undef TEST_BAD_ALL + + a = "FF"; + b = a.leftRef(-1); + b.toULongLong(&ok, 10); + QVERIFY(!ok); + + a = "FF"; + b = a.leftRef(-1); + b.toULongLong(&ok, 0); + QVERIFY(!ok); + +#ifdef QT_NO_FPU + double d = 3.40282346638528e+38; // slightly off FLT_MAX when using hardfloats +#else + double d = 3.4028234663852886e+38; // FLT_MAX +#endif + QString::number(d, 'e', 17).leftRef(-1).toFloat(&ok); + QVERIFY(ok); + QString::number(d + 1e32, 'e', 17).leftRef(-1).toFloat(&ok); + QVERIFY(!ok); + a = QString::number(-d, 'e', 17).leftRef(-1).toFloat(&ok); + QVERIFY(ok); + QString::number(-d - 1e32, 'e', 17).leftRef(-1).toFloat(&ok); + QVERIFY(!ok); + QString::number(d + 1e32, 'e', 17).leftRef(-1).toDouble(&ok); + QVERIFY(ok); + QString::number(-d - 1e32, 'e', 17).leftRef(-1).toDouble(&ok); + QVERIFY(ok); +} + +void tst_QStringRef::toUShort() +{ + QString a; + QStringRef b; + bool ok; + QCOMPARE(b.toUShort(), ushort(0)); + QCOMPARE(b.toUShort(&ok), ushort(0)); + QVERIFY(!ok); + + a = ""; + b = a.leftRef(-1); + QCOMPARE(b.toUShort(), ushort(0)); + QCOMPARE(b.toUShort(&ok), ushort(0)); + QVERIFY(!ok); + + a = "COMPARE"; + b = a.leftRef(-1); + QCOMPARE(b.toUShort(), ushort(0)); + QCOMPARE(b.toUShort(&ok), ushort(0)); + QVERIFY(!ok); + + a = "123"; + b = a.leftRef(-1); + QCOMPARE(b.toUShort(), ushort(123)); + QCOMPARE(b.toUShort(&ok), ushort(123)); + QVERIFY(ok); + + a = "123A"; + b = a.leftRef(-1); + QCOMPARE(b.toUShort(), ushort(0)); + QCOMPARE(b.toUShort(&ok), ushort(0)); + QVERIFY(!ok); + + a = "1234567"; + b = a.leftRef(-1); + QCOMPARE(b.toUShort(), ushort(0)); + QCOMPARE(b.toUShort(&ok), ushort(0)); + QVERIFY(!ok); + + a = "aaa123aaa"; + b = a.leftRef(-1); + QCOMPARE(b.toUShort(), ushort(0)); + QCOMPARE(b.toUShort(&ok), ushort(0)); + QVERIFY(!ok); + + a = "aaa123"; + b = a.leftRef(-1); + QCOMPARE(b.toUShort(), ushort(0)); + QCOMPARE(b.toUShort(&ok), ushort(0)); + QVERIFY(!ok); + + a = "123aaa"; + b = a.leftRef(-1); + QCOMPARE(b.toUShort(), ushort(0)); + QCOMPARE(b.toUShort(&ok), ushort(0)); + QVERIFY(!ok); + + a = "32767"; + b = a.leftRef(-1); + QCOMPARE(b.toUShort(), ushort(32767)); + QCOMPARE(b.toUShort(&ok), ushort(32767)); + QVERIFY(ok); + + a = "-32767"; + b = a.leftRef(-1); + QCOMPARE(b.toUShort(), ushort(0)); + QCOMPARE(b.toUShort(&ok), ushort(0)); + QVERIFY(!ok); + + a = "65535"; + b = a.leftRef(-1); + QCOMPARE(b.toUShort(), ushort(65535)); + QCOMPARE(b.toUShort(&ok), ushort(65535)); + QVERIFY(ok); + + if (sizeof(short) == 2) { + a = "65536"; + b = a.leftRef(-1); + QCOMPARE(b.toUShort(), ushort(0)); + QCOMPARE(b.toUShort(&ok), ushort(0)); + QVERIFY(!ok); + + a = "123456"; + b = a.leftRef(-1); + QCOMPARE(b.toUShort(), ushort(0)); + QCOMPARE(b.toUShort(&ok), ushort(0)); + QVERIFY(!ok); + } +} + +void tst_QStringRef::toShort() +{ + QString a; + QStringRef b; + bool ok; + QCOMPARE(b.toShort(), short(0)); + QCOMPARE(b.toShort(&ok), short(0)); + QVERIFY(!ok); + + a = ""; + b = a.leftRef(-1); + QCOMPARE(b.toShort(), short(0)); + QCOMPARE(b.toShort(&ok), short(0)); + QVERIFY(!ok); + + a = "COMPARE"; + b = a.leftRef(-1); + QCOMPARE(b.toShort(), short(0)); + QCOMPARE(b.toShort(&ok), short(0)); + QVERIFY(!ok); + + a = "123"; + b = a.leftRef(-1); + QCOMPARE(b.toShort(), short(123)); + QCOMPARE(b.toShort(&ok), short(123)); + QVERIFY(ok); + + a = "123A"; + b = a.leftRef(-1); + QCOMPARE(b.toShort(), short(0)); + QCOMPARE(b.toShort(&ok), short(0)); + QVERIFY(!ok); + + a = "1234567"; + b = a.leftRef(-1); + QCOMPARE(b.toShort(), short(0)); + QCOMPARE(b.toShort(&ok), short(0)); + QVERIFY(!ok); + + a = "aaa123aaa"; + b = a.leftRef(-1); + QCOMPARE(b.toShort(), short(0)); + QCOMPARE(b.toShort(&ok), short(0)); + QVERIFY(!ok); + + a = "aaa123"; + b = a.leftRef(-1); + QCOMPARE(b.toShort(), short(0)); + QCOMPARE(b.toShort(&ok), short(0)); + QVERIFY(!ok); + + a = "123aaa"; + b = a.leftRef(-1); + QCOMPARE(b.toShort(), short(0)); + QCOMPARE(b.toShort(&ok), short(0)); + QVERIFY(!ok); + + a = "32767"; + b = a.leftRef(-1); + QCOMPARE(b.toShort(), short(32767)); + QCOMPARE(b.toShort(&ok), short(32767)); + QVERIFY(ok); + + a = "-32767"; + b = a.leftRef(-1); + QCOMPARE(b.toShort(), short(-32767)); + QCOMPARE(b.toShort(&ok), short(-32767)); + QVERIFY(ok); + + a = "-32768"; + b = a.leftRef(-1); + QCOMPARE(b.toShort(), short(-32768)); + QCOMPARE(b.toShort(&ok), short(-32768)); + QVERIFY(ok); + + if (sizeof(short) == 2) { + a = "32768"; + b = a.leftRef(-1); + QCOMPARE(b.toShort(), short(0)); + QCOMPARE(b.toShort(&ok), short(0)); + QVERIFY(!ok); + + a = "-32769"; + b = a.leftRef(-1); + QCOMPARE(b.toShort(), short(0)); + QCOMPARE(b.toShort(&ok), short(0)); + QVERIFY(!ok); + } +} + +void tst_QStringRef::toInt() +{ + QString a; + QStringRef b; + bool ok; + QCOMPARE(b.toInt(), 0); + QCOMPARE(b.toInt(&ok), 0); + QVERIFY(!ok); + + a = ""; + b = a.leftRef(-1); + QCOMPARE(b.toInt(), 0); + QCOMPARE(b.toInt(&ok), 0); + QVERIFY(!ok); + + a = "COMPARE"; + b = a.leftRef(-1); + QCOMPARE(b.toInt(), 0); + QCOMPARE(b.toInt(&ok), 0); + QVERIFY(!ok); + + a = "123"; + b = a.leftRef(-1); + QCOMPARE(b.toInt(), 123); + QCOMPARE(b.toInt(&ok), 123); + QVERIFY(ok); + + a = "123A"; + b = a.leftRef(-1); + QCOMPARE(b.toInt(), 0); + QCOMPARE(b.toInt(&ok), 0); + QVERIFY(!ok); + + a = "1234567"; + b = a.leftRef(-1); + QCOMPARE(b.toInt(), 1234567); + QCOMPARE(b.toInt(&ok), 1234567); + QVERIFY(ok); + + a = "12345678901234"; + b = a.leftRef(-1); + QCOMPARE(b.toInt(), 0); + QCOMPARE(b.toInt(&ok), 0); + QVERIFY(!ok); + + a = "3234567890"; + b = a.leftRef(-1); + QCOMPARE(b.toInt(), 0); + QCOMPARE(b.toInt(&ok), 0); + QVERIFY(!ok); + + a = "aaa12345aaa"; + b = a.leftRef(-1); + QCOMPARE(b.toInt(), 0); + QCOMPARE(b.toInt(&ok), 0); + QVERIFY(!ok); + + a = "aaa12345"; + b = a.leftRef(-1); + QCOMPARE(b.toInt(), 0); + QCOMPARE(b.toInt(&ok), 0); + QVERIFY(!ok); + + a = "12345aaa"; + b = a.leftRef(-1); + QCOMPARE(b.toInt(), 0); + QCOMPARE(b.toInt(&ok), 0); + QVERIFY(!ok); + + a = "2147483647"; // 2**31 - 1 + b = a.leftRef(-1); + QCOMPARE(b.toInt(), 2147483647); + QCOMPARE(b.toInt(&ok), 2147483647); + QVERIFY(ok); + + if (sizeof(int) == 4) { + a = "-2147483647"; // -(2**31 - 1) + b = a.leftRef(-1); + QCOMPARE(b.toInt(), -2147483647); + QCOMPARE(b.toInt(&ok), -2147483647); + QVERIFY(ok); + + a = "2147483648"; // 2**31 + b = a.leftRef(-1); + QCOMPARE(b.toInt(), 0); + QCOMPARE(b.toInt(&ok), 0); + QVERIFY(!ok); + + a = "-2147483648"; // -2**31 + b = a.leftRef(-1); + QCOMPARE(b.toInt(), -2147483647 - 1); + QCOMPARE(b.toInt(&ok), -2147483647 - 1); + QVERIFY(ok); + + a = "2147483649"; // 2**31 + 1 + b = a.leftRef(-1); + QCOMPARE(b.toInt(), 0); + QCOMPARE(b.toInt(&ok), 0); + QVERIFY(!ok); + } +} + +void tst_QStringRef::toUInt() +{ + bool ok; + QString a; + QStringRef b; + a = "3234567890"; + b = a.leftRef(-1); + QCOMPARE(b.toUInt(&ok), 3234567890u); + QVERIFY(ok); + + a = "-50"; + b = a.leftRef(-1); + QCOMPARE(b.toUInt(), 0u); + QCOMPARE(b.toUInt(&ok), 0u); + QVERIFY(!ok); + + a = "4294967295"; // 2**32 - 1 + b = a.leftRef(-1); + QCOMPARE(b.toUInt(), 4294967295u); + QCOMPARE(b.toUInt(&ok), 4294967295u); + QVERIFY(ok); + + if (sizeof(int) == 4) { + a = "4294967296"; // 2**32 + b = a.leftRef(-1); + QCOMPARE(b.toUInt(), 0u); + QCOMPARE(b.toUInt(&ok), 0u); + QVERIFY(!ok); + } +} + +///////////////////////////// to*Long ////////////////////////////////////// + +void tst_QStringRef::toULong_data() +{ + QTest::addColumn<QString>("str"); + QTest::addColumn<int>("base"); + QTest::addColumn<ulong>("result"); + QTest::addColumn<bool>("ok"); + + QTest::newRow("default") << QString() << 10 << 0UL << false; + QTest::newRow("empty") << QString("") << 10 << 0UL << false; + QTest::newRow("ulong1") << QString("3234567890") << 10 << 3234567890UL << true; + QTest::newRow("ulong2") << QString("fFFfFfFf") << 16 << 0xFFFFFFFFUL << true; +} + +void tst_QStringRef::toULong() +{ + QFETCH(QString, str); + QFETCH(int, base); + QFETCH(ulong, result); + QFETCH(bool, ok); + QStringRef strRef = str.leftRef(-1); + + bool b; + QCOMPARE(strRef.toULong(0, base), result); + QCOMPARE(strRef.toULong(&b, base), result); + QCOMPARE(b, ok); +} + +void tst_QStringRef::toLong_data() +{ + QTest::addColumn<QString>("str"); + QTest::addColumn<int>("base"); + QTest::addColumn<long>("result"); + QTest::addColumn<bool>("ok"); + + QTest::newRow("default") << QString() << 10 << 0L << false; + QTest::newRow("empty") << QString("") << 10 << 0L << false; + QTest::newRow("normal") << QString("7fFFfFFf") << 16 << 0x7fFFfFFfL << true; + QTest::newRow("long_max") << QString("2147483647") << 10 << 2147483647L << true; + if (sizeof(long) == 4) { + QTest::newRow("long_max+1") << QString("2147483648") << 10 << 0L << false; + QTest::newRow("long_min-1") << QString("-80000001") << 16 << 0L << false; + } + QTest::newRow("negative") << QString("-7fffffff") << 16 << -0x7fffffffL << true; +// QTest::newRow("long_min") << QString("-80000000") << 16 << 0x80000000uL << true; +} + +void tst_QStringRef::toLong() +{ + QFETCH(QString, str); + QFETCH(int, base); + QFETCH(long, result); + QFETCH(bool, ok); + QStringRef strRef = str.leftRef(-1); + + bool b; + QCOMPARE(strRef.toLong(0, base), result); + QCOMPARE(strRef.toLong(&b, base), result); + QCOMPARE(b, ok); +} + + +////////////////////////// to*LongLong ////////////////////////////////////// + +void tst_QStringRef::toULongLong() +{ + QString str; + QStringRef strRef; + bool ok; + str = "18446744073709551615"; // ULLONG_MAX + strRef = str.leftRef(-1); + QCOMPARE(strRef.toULongLong(0), Q_UINT64_C(18446744073709551615)); + QCOMPARE(strRef.toULongLong(&ok), Q_UINT64_C(18446744073709551615)); + QVERIFY(ok); + + str = "18446744073709551616"; // ULLONG_MAX + 1 + strRef = str.leftRef(-1); + QCOMPARE(strRef.toULongLong(0), Q_UINT64_C(0)); + QCOMPARE(strRef.toULongLong(&ok), Q_UINT64_C(0)); + QVERIFY(!ok); + + str = "-150"; + strRef = str.leftRef(-1); + QCOMPARE(strRef.toULongLong(0), Q_UINT64_C(0)); + QCOMPARE(strRef.toULongLong(&ok), Q_UINT64_C(0)); + QVERIFY(!ok); +} + +void tst_QStringRef::toLongLong() +{ + QString str; + QStringRef strRef; + bool ok; + + str = "9223372036854775807"; // LLONG_MAX + strRef = str.leftRef(-1); + QCOMPARE(strRef.toLongLong(0), Q_INT64_C(9223372036854775807)); + QCOMPARE(strRef.toLongLong(&ok), Q_INT64_C(9223372036854775807)); + QVERIFY(ok); + + str = "-9223372036854775808"; // LLONG_MIN + strRef = str.leftRef(-1); + QCOMPARE(strRef.toLongLong(0), + -Q_INT64_C(9223372036854775807) - Q_INT64_C(1)); + QCOMPARE(strRef.toLongLong(&ok), + -Q_INT64_C(9223372036854775807) - Q_INT64_C(1)); + QVERIFY(ok); + + str = "aaaa9223372036854775807aaaa"; + strRef = str.leftRef(-1); + QCOMPARE(strRef.toLongLong(0), Q_INT64_C(0)); + QCOMPARE(strRef.toLongLong(&ok), Q_INT64_C(0)); + QVERIFY(!ok); + + str = "9223372036854775807aaaa"; + strRef = str.leftRef(-1); + QCOMPARE(strRef.toLongLong(0), Q_INT64_C(0)); + QCOMPARE(strRef.toLongLong(&ok), Q_INT64_C(0)); + QVERIFY(!ok); + + str = "aaaa9223372036854775807"; + strRef = str.leftRef(-1); + QCOMPARE(strRef.toLongLong(0), Q_INT64_C(0)); + QCOMPARE(strRef.toLongLong(&ok), Q_INT64_C(0)); + QVERIFY(!ok); + + static char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + for (int i = 0; i < 36; ++i) { + for (int j = 0; j < 36; ++j) { + for (int k = 0; k < 36; ++k) { + QString str; + str += QChar(digits[i]); + str += QChar(digits[j]); + str += QChar(digits[k]); + strRef = str.leftRef(-1); + qlonglong value = (((i * 36) + j) * 36) + k; + QVERIFY(strRef.toLongLong(0, 36) == value); + } + } + } +} + +//////////////////////////////////////////////////////////////////////////// + +void tst_QStringRef::toFloat() +{ + QString a; + QStringRef b; + bool ok; + a = "0.000000000931322574615478515625"; + b = a.leftRef(-1); + QCOMPARE(b.toFloat(&ok), float(0.000000000931322574615478515625)); + QVERIFY(ok); +} + +void tst_QStringRef::toDouble_data() +{ + QTest::addColumn<QString>("str"); + QTest::addColumn<double>("result"); + QTest::addColumn<bool>("result_ok"); + + QTest::newRow("ok00") << QString("0.000000000931322574615478515625") << 0.000000000931322574615478515625 << true; + QTest::newRow("ok01") << QString(" 123.45") << 123.45 << true; + + QTest::newRow("ok02") << QString("0.1e10") << 0.1e10 << true; + QTest::newRow("ok03") << QString("0.1e-10") << 0.1e-10 << true; + + QTest::newRow("ok04") << QString("1e10") << 1.0e10 << true; + QTest::newRow("ok05") << QString("1e+10") << 1.0e10 << true; + QTest::newRow("ok06") << QString("1e-10") << 1.0e-10 << true; + + QTest::newRow("ok07") << QString(" 1e10") << 1.0e10 << true; + QTest::newRow("ok08") << QString(" 1e+10") << 1.0e10 << true; + QTest::newRow("ok09") << QString(" 1e-10") << 1.0e-10 << true; + + QTest::newRow("ok10") << QString("1.") << 1.0 << true; + QTest::newRow("ok11") << QString(".1") << 0.1 << true; + + QTest::newRow("wrong00") << QString("123.45 ") << 123.45 << true; + QTest::newRow("wrong01") << QString(" 123.45 ") << 123.45 << true; + + QTest::newRow("wrong02") << QString("aa123.45aa") << 0.0 << false; + QTest::newRow("wrong03") << QString("123.45aa") << 0.0 << false; + QTest::newRow("wrong04") << QString("123erf") << 0.0 << false; + + QTest::newRow("wrong05") << QString("abc") << 0.0 << false; + QTest::newRow("wrong06") << QString() << 0.0 << false; + QTest::newRow("wrong07") << QString("") << 0.0 << false; +} + +void tst_QStringRef::toDouble() +{ + QFETCH(QString, str); + QFETCH(bool, result_ok); + QStringRef strRef = str.leftRef(-1); + bool ok; + double d = strRef.toDouble(&ok); + if (result_ok) { + QTEST(d, "result"); + QVERIFY(ok); + } else { + QVERIFY(!ok); + } +} + +void tst_QStringRef::integer_conversion_data() +{ + QTest::addColumn<QString>("num_str"); + QTest::addColumn<int>("base"); + QTest::addColumn<bool>("good"); + QTest::addColumn<qlonglong>("num"); + + QTest::newRow("C empty 0") << QString("") << 0 << false << (qlonglong)0; + QTest::newRow("C empty 8") << QString("") << 8 << false << (qlonglong)0; + QTest::newRow("C empty 10") << QString("") << 10 << false << (qlonglong)0; + QTest::newRow("C empty 16") << QString("") << 16 << false << (qlonglong)0; + + QTest::newRow("C null 0") << QString() << 0 << false << (qlonglong)0; + QTest::newRow("C null 8") << QString() << 8 << false << (qlonglong)0; + QTest::newRow("C null 10") << QString() << 10 << false << (qlonglong)0; + QTest::newRow("C null 16") << QString() << 16 << false << (qlonglong)0; + + QTest::newRow("C -0xf 0") << QString(" -0xf") << 0 << true << (qlonglong)-15; + QTest::newRow("C -0xf 0") << QString("-0xf ") << 0 << true << (qlonglong)-15; + QTest::newRow("C \t0xf\t 0") << QString("\t0xf\t") << 0 << true << (qlonglong)15; + QTest::newRow("C -010 0") << QString(" -010") << 0 << true << (qlonglong)-8; + QTest::newRow("C 010 0") << QString("010 ") << 0 << true << (qlonglong)8; + QTest::newRow("C \t-010\t 0") << QString("\t-010\t") << 0 << true << (qlonglong)-8; + QTest::newRow("C 123 10") << QString(" 123") << 10 << true << (qlonglong)123; + QTest::newRow("C 123 10") << QString("123 ") << 10 << true << (qlonglong)123; + QTest::newRow("C \t123\t 10") << QString("\t123\t") << 10 << true << (qlonglong)123; + QTest::newRow("C -0xf 16") << QString(" -0xf") << 16 << true << (qlonglong)-15; + QTest::newRow("C -0xf 16") << QString("-0xf ") << 16 << true << (qlonglong)-15; + QTest::newRow("C \t0xf\t 16") << QString("\t0xf\t") << 16 << true << (qlonglong)15; + + QTest::newRow("C -0 0") << QString("-0") << 0 << true << (qlonglong)0; + QTest::newRow("C -0 8") << QString("-0") << 8 << true << (qlonglong)0; + QTest::newRow("C -0 10") << QString("-0") << 10 << true << (qlonglong)0; + QTest::newRow("C -0 16") << QString("-0") << 16 << true << (qlonglong)0; + + QTest::newRow("C 1.234 10") << QString("1.234") << 10 << false << (qlonglong)0; + QTest::newRow("C 1,234 10") << QString("1,234") << 10 << false << (qlonglong)0; + + QTest::newRow("C 0x 0") << QString("0x") << 0 << false << (qlonglong)0; + QTest::newRow("C 0x 16") << QString("0x") << 16 << false << (qlonglong)0; + + QTest::newRow("C 10 0") << QString("10") << 0 << true << (qlonglong)10; + QTest::newRow("C 010 0") << QString("010") << 0 << true << (qlonglong)8; + QTest::newRow("C 0x10 0") << QString("0x10") << 0 << true << (qlonglong)16; + QTest::newRow("C 10 8") << QString("10") << 8 << true << (qlonglong)8; + QTest::newRow("C 010 8") << QString("010") << 8 << true << (qlonglong)8; + QTest::newRow("C 0x10 8") << QString("0x10") << 8 << false << (qlonglong)0; + QTest::newRow("C 10 10") << QString("10") << 10 << true << (qlonglong)10; + QTest::newRow("C 010 10") << QString("010") << 10 << true << (qlonglong)10; + QTest::newRow("C 0x10 10") << QString("0x10") << 10 << false << (qlonglong)0; + QTest::newRow("C 10 16") << QString("10") << 16 << true << (qlonglong)16; + QTest::newRow("C 010 16") << QString("010") << 16 << true << (qlonglong)16; + QTest::newRow("C 0x10 16") << QString("0x10") << 16 << true << (qlonglong)16; + + QTest::newRow("C -10 0") << QString("-10") << 0 << true << (qlonglong)-10; + QTest::newRow("C -010 0") << QString("-010") << 0 << true << (qlonglong)-8; + QTest::newRow("C -0x10 0") << QString("-0x10") << 0 << true << (qlonglong)-16; + QTest::newRow("C -10 8") << QString("-10") << 8 << true << (qlonglong)-8; + QTest::newRow("C -010 8") << QString("-010") << 8 << true << (qlonglong)-8; + QTest::newRow("C -0x10 8") << QString("-0x10") << 8 << false << (qlonglong)0; + QTest::newRow("C -10 10") << QString("-10") << 10 << true << (qlonglong)-10; + QTest::newRow("C -010 10") << QString("-010") << 10 << true << (qlonglong)-10; + QTest::newRow("C -0x10 10") << QString("-0x10") << 10 << false << (qlonglong)0; + QTest::newRow("C -10 16") << QString("-10") << 16 << true << (qlonglong)-16; + QTest::newRow("C -010 16") << QString("-010") << 16 << true << (qlonglong)-16; + QTest::newRow("C -0x10 16") << QString("-0x10") << 16 << true << (qlonglong)-16; + + // Let's try some Arabic + const quint16 arabic_str[] = { 0x0661, 0x0662, 0x0663, 0x0664, 0x0000 }; // "1234" + QTest::newRow("ar_SA 1234 0") << QString::fromUtf16(arabic_str) << 0 << false << (qlonglong)0; +} + +void tst_QStringRef::integer_conversion() +{ + QFETCH(QString, num_str); + QFETCH(int, base); + QFETCH(bool, good); + QFETCH(qlonglong, num); + QStringRef num_strRef = num_str.leftRef(-1); + + bool ok; + qlonglong d = num_strRef.toLongLong(&ok, base); + QCOMPARE(ok, good); + + if (ok) { + QCOMPARE(d, num); + } +} + +void tst_QStringRef::double_conversion_data() +{ + QTest::addColumn<QString>("num_str"); + QTest::addColumn<bool>("good"); + QTest::addColumn<double>("num"); + + // The good... + + QTest::newRow("C 1") << QString("1") << true << 1.0; + QTest::newRow("C 1.0") << QString("1.0") << true << 1.0; + QTest::newRow("C 1.234") << QString("1.234") << true << 1.234; + QTest::newRow("C 1.234e-10") << QString("1.234e-10") << true << 1.234e-10; + QTest::newRow("C 1.234E10") << QString("1.234E10") << true << 1.234e10; + QTest::newRow("C 1e10") << QString("1e10") << true << 1.0e10; + + // The bad... + + QTest::newRow("C empty") << QString("") << false << 0.0; + QTest::newRow("C null") << QString() << false << 0.0; + QTest::newRow("C .") << QString(".") << false << 0.0; + QTest::newRow("C 1e") << QString("1e") << false << 0.0; + QTest::newRow("C 1,") << QString("1,") << false << 0.0; + QTest::newRow("C 1,0") << QString("1,0") << false << 0.0; + QTest::newRow("C 1,000") << QString("1,000") << false << 0.0; + QTest::newRow("C 1e1.0") << QString("1e1.0") << false << 0.0; + QTest::newRow("C 1e+") << QString("1e+") << false << 0.0; + QTest::newRow("C 1e-") << QString("1e-") << false << 0.0; + QTest::newRow("de_DE 1,0") << QString("1,0") << false << 0.0; + QTest::newRow("de_DE 1,234") << QString("1,234") << false << 0.0; + QTest::newRow("de_DE 1,234e-10") << QString("1,234e-10") << false << 0.0; + QTest::newRow("de_DE 1,234E10") << QString("1,234E10") << false << 0.0; + + // And the ugly... + + QTest::newRow("C .1") << QString(".1") << true << 0.1; + QTest::newRow("C -.1") << QString("-.1") << true << -0.1; + QTest::newRow("C 1.") << QString("1.") << true << 1.0; + QTest::newRow("C 1.E10") << QString("1.E10") << true << 1.0e10; + QTest::newRow("C 1e+10") << QString("1e+10") << true << 1.0e+10; + QTest::newRow("C 1") << QString(" 1") << true << 1.0; + QTest::newRow("C 1 ") << QString("1 ") << true << 1.0; + + // Let's try some Arabic + const quint16 arabic_str[] = { 0x0660, 0x066B, 0x0661, 0x0662, + 0x0663, 0x0664, 0x0065, 0x0662, + 0x0000 }; // "0.1234e2" + QTest::newRow("ar_SA") << QString::fromUtf16(arabic_str) << false << 0.0; +} + +void tst_QStringRef::double_conversion() +{ +#define MY_DOUBLE_EPSILON (2.22045e-16) + + QFETCH(QString, num_str); + QFETCH(bool, good); + QFETCH(double, num); + QStringRef num_strRef = num_str.leftRef(-1); + + bool ok; + double d = num_strRef.toDouble(&ok); + QCOMPARE(ok, good); + + if (ok) { + double diff = d - num; + if (diff < 0) + diff = -diff; + QVERIFY(diff <= MY_DOUBLE_EPSILON); + } +} + +void tst_QStringRef::trimmed() +{ + QString a; + QStringRef b; + a = "Text"; + b = a.leftRef(-1); + QCOMPARE(b.compare(QStringLiteral("Text")), 0); + QCOMPARE(b.trimmed().compare(QStringLiteral("Text")), 0); + a = " "; + b = a.leftRef(-1); + QCOMPARE(b.compare(QStringLiteral(" ")), 0); + QCOMPARE(b.trimmed().compare(QStringLiteral("")), 0); + a = " a "; + b = a.leftRef(-1); + QCOMPARE(b.trimmed().compare(QStringLiteral("a")), 0); + a = "Text a "; + b = a.midRef(4); + QCOMPARE(b.compare(QStringLiteral(" a ")), 0); + QCOMPARE(b.trimmed().compare(QStringLiteral("a")), 0); +} + QTEST_APPLESS_MAIN(tst_QStringRef) #include "tst_qstringref.moc" diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp index bda3a2596f..c19080e345 100644 --- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp +++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp @@ -58,6 +58,7 @@ private slots: void count(); void first(); void last(); + void squeeze(); }; int fooCtor = 0; @@ -653,5 +654,28 @@ void tst_QVarLengthArray::last() QCOMPARE(list.length(), 1); } +void tst_QVarLengthArray::squeeze() +{ + QVarLengthArray<int> list; + int sizeOnStack = list.capacity(); + int sizeOnHeap = sizeOnStack * 2; + list.resize(0); + QCOMPARE(list.capacity(), sizeOnStack); + list.resize(sizeOnHeap); + QCOMPARE(list.capacity(), sizeOnHeap); + list.resize(sizeOnStack); + QCOMPARE(list.capacity(), sizeOnHeap); + list.resize(0); + QCOMPARE(list.capacity(), sizeOnHeap); + list.squeeze(); + QCOMPARE(list.capacity(), sizeOnStack); + list.resize(sizeOnStack); + list.squeeze(); + QCOMPARE(list.capacity(), sizeOnStack); + list.resize(sizeOnHeap); + list.squeeze(); + QCOMPARE(list.capacity(), sizeOnHeap); +} + QTEST_APPLESS_MAIN(tst_QVarLengthArray) #include "tst_qvarlengtharray.moc" diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro index 100409e58b..f8b2437d35 100644 --- a/tests/auto/corelib/tools/tools.pro +++ b/tests/auto/corelib/tools/tools.pro @@ -22,6 +22,7 @@ SUBDIRS=\ qlocale \ qmap \ qmargins \ + qmessageauthenticationcode \ qpair \ qpoint \ qpointf \ diff --git a/tests/auto/corelib/xml/xml.pro b/tests/auto/corelib/xml/xml.pro index 53836cb7f0..20519edf1b 100644 --- a/tests/auto/corelib/xml/xml.pro +++ b/tests/auto/corelib/xml/xml.pro @@ -1,3 +1,3 @@ TEMPLATE=subdirs -SUBDIRS=\ +qtHaveModule(network): SUBDIRS= \ qxmlstream diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp index c56a47bbc6..1da7f8a92a 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp @@ -1200,6 +1200,19 @@ void tst_QDBusConnection::registerVirtualObject() QVERIFY(!con.registerVirtualObject(path, &obj, QDBusConnection::SubPath)); QCOMPARE(con.objectRegisteredAt(path), static_cast<QObject *>(0)); } + + { + // Register object, make sure no SubPath handling object can be registered on a parent path. + // (same as above, but deeper) + QObject objectAtSubPath; + QVERIFY(con.registerObject(childChildPath, &objectAtSubPath)); + QCOMPARE(con.objectRegisteredAt(childChildPath), static_cast<QObject *>(&objectAtSubPath)); + + VirtualObject obj; + QVERIFY(!con.registerVirtualObject(path, &obj, QDBusConnection::SubPath)); + QCOMPARE(con.objectRegisteredAt(path), static_cast<QObject *>(0)); + } + QCOMPARE(con.objectRegisteredAt(path), static_cast<QObject *>(0)); QCOMPARE(con.objectRegisteredAt(childPath), static_cast<QObject *>(0)); QCOMPARE(con.objectRegisteredAt(childChildPath), static_cast<QObject *>(0)); diff --git a/tests/auto/dbus/qdbuspendingreply/tst_qdbuspendingreply.cpp b/tests/auto/dbus/qdbuspendingreply/tst_qdbuspendingreply.cpp index 841e09c865..a45a0fefbb 100644 --- a/tests/auto/dbus/qdbuspendingreply/tst_qdbuspendingreply.cpp +++ b/tests/auto/dbus/qdbuspendingreply/tst_qdbuspendingreply.cpp @@ -572,6 +572,8 @@ void tst_QDBusPendingReply::errors() QVERIFY(rint.isError()); error = rint.error(); VERIFY_ERROR(error); + int dummyint = rint; + QCOMPARE(dummyint, int()); QDBusPendingReply<int,int> rintint(iface->asyncCall("sendError")); rintint.waitForFinished(); @@ -579,6 +581,9 @@ void tst_QDBusPendingReply::errors() QVERIFY(rintint.isError()); error = rintint.error(); VERIFY_ERROR(error); + dummyint = rintint; + QCOMPARE(dummyint, int()); + QCOMPARE(rintint.argumentAt<1>(), int()); QDBusPendingReply<QString> rstring(iface->asyncCall("sendError")); rstring.waitForFinished(); @@ -586,6 +591,8 @@ void tst_QDBusPendingReply::errors() QVERIFY(rstring.isError()); error = rstring.error(); VERIFY_ERROR(error); + QString dummystring = rstring; + QCOMPARE(dummystring, QString()); } QTEST_MAIN(tst_QDBusPendingReply) diff --git a/tests/auto/dbus/qdbusreply/tst_qdbusreply.cpp b/tests/auto/dbus/qdbusreply/tst_qdbusreply.cpp index 5e60e468a2..8b0fa92adf 100644 --- a/tests/auto/dbus/qdbusreply/tst_qdbusreply.cpp +++ b/tests/auto/dbus/qdbusreply/tst_qdbusreply.cpp @@ -97,6 +97,7 @@ private slots: void simpleTypes(); void complexTypes(); void wrongTypes(); + void error(); }; class TypesInterface: public QDBusAbstractAdaptor @@ -372,6 +373,30 @@ void tst_QDBusReply::wrongTypes() QVERIFY(!rstruct.isValid()); } +void tst_QDBusReply::error() +{ + { + // Wrong type + QDBusReply<bool> result = iface->call(QDBus::BlockWithGui, "retrieveInt"); + QVERIFY(result.error().isValid()); + } + { + // Wrong type, const version + const QDBusReply<bool> result = iface->call(QDBus::BlockWithGui, "retrieveInt"); + QVERIFY(result.error().isValid()); + } + { + // Ok type + QDBusReply<void> result = iface->call(QDBus::BlockWithGui, "retrieveInt"); + QVERIFY(!result.error().isValid()); + } + { + // Ok type, const version + const QDBusReply<void> result = iface->call(QDBus::BlockWithGui, "retrieveInt"); + QVERIFY(!result.error().isValid()); + } +} + QTEST_MAIN(tst_QDBusReply) #include "tst_qdbusreply.moc" diff --git a/tests/auto/gui/image/image.pro b/tests/auto/gui/image/image.pro index 1ef52df4ba..9199763c40 100644 --- a/tests/auto/gui/image/image.pro +++ b/tests/auto/gui/image/image.pro @@ -11,6 +11,9 @@ SUBDIRS=\ qpicture \ qicon \ +!qtHaveModule(network): SUBDIRS -= \ + qimagereader + !contains(QT_CONFIG, private_tests): SUBDIRS -= \ qpixmapcache \ diff --git a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp index 4b3db26685..b684231e10 100644 --- a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp @@ -94,6 +94,7 @@ private slots: void multiWordNamedColorXPM(); void supportedFormats(); + void supportedMimeTypes(); void readFromDevice_data(); void readFromDevice(); @@ -571,6 +572,26 @@ void tst_QImageReader::supportedFormats() QCOMPARE(formatSet.size(), formats.size()); } +void tst_QImageReader::supportedMimeTypes() +{ + QList<QByteArray> mimeTypes = QImageReader::supportedMimeTypes(); + QList<QByteArray> sortedMimeTypes = mimeTypes; + qSort(sortedMimeTypes); + + // check that the list is sorted + QCOMPARE(mimeTypes, sortedMimeTypes); + + QSet<QByteArray> mimeTypeSet; + foreach (QByteArray mimeType, mimeTypes) + mimeTypeSet << mimeType; + + // check the list as a minimum contains image/bmp + QVERIFY(mimeTypeSet.contains("image/bmp")); + + // check that the list does not contain duplicates + QCOMPARE(mimeTypeSet.size(), mimeTypes.size()); +} + void tst_QImageReader::setBackgroundColor_data() { QTest::addColumn<QString>("fileName"); diff --git a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp index 3c36482d62..f1d0e227f6 100644 --- a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp +++ b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp @@ -81,6 +81,7 @@ private slots: void writeImage2_data(); void writeImage2(); void supportedFormats(); + void supportedMimeTypes(); void writeToInvalidDevice(); @@ -352,6 +353,26 @@ void tst_QImageWriter::supportedFormats() QCOMPARE(formatSet.size(), formats.size()); } +void tst_QImageWriter::supportedMimeTypes() +{ + QList<QByteArray> mimeTypes = QImageWriter::supportedMimeTypes(); + QList<QByteArray> sortedMimeTypes = mimeTypes; + qSort(sortedMimeTypes); + + // check that the list is sorted + QCOMPARE(mimeTypes, sortedMimeTypes); + + QSet<QByteArray> mimeTypeSet; + foreach (QByteArray mimeType, mimeTypes) + mimeTypeSet << mimeType; + + // check the list as a minimum contains image/bmp + QVERIFY(mimeTypeSet.contains("image/bmp")); + + // check that the list does not contain duplicates + QCOMPARE(mimeTypeSet.size(), mimeTypes.size()); +} + void tst_QImageWriter::writeToInvalidDevice() { QLatin1String fileName("/these/directories/do/not/exist/001.png"); diff --git a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp index f5298a1690..b9b61425da 100644 --- a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp +++ b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp @@ -114,6 +114,7 @@ private slots: void convertFromImageNoDetach(); void convertFromImageDetach(); + void convertFromImageCacheKey(); #if defined(Q_OS_WIN) void toWinHBITMAP_data(); @@ -780,6 +781,28 @@ void tst_QPixmap::convertFromImageDetach() QVERIFY(copy.isDetached()); } +void tst_QPixmap::convertFromImageCacheKey() +{ + QPixmap randomPixmap(10, 10); + if (randomPixmap.handle()->classId() != QPlatformPixmap::RasterClass) + QSKIP("Test only valid for raster pixmaps"); + + //first get the screen format + QImage::Format screenFormat = randomPixmap.toImage().format(); + QVERIFY(screenFormat != QImage::Format_Invalid); + + QImage orig(100,100, screenFormat); + orig.fill(0); + + QPixmap pix = QPixmap::fromImage(orig); + QImage copy = pix.toImage(); + + QVERIFY(copy.format() == screenFormat); + + QCOMPARE(orig.cacheKey(), pix.cacheKey()); + QCOMPARE(copy.cacheKey(), pix.cacheKey()); +} + #if defined(Q_OS_WIN) QT_BEGIN_NAMESPACE diff --git a/tests/auto/gui/kernel/kernel.pro b/tests/auto/gui/kernel/kernel.pro index 7e3f25d377..85a81de632 100644 --- a/tests/auto/gui/kernel/kernel.pro +++ b/tests/auto/gui/kernel/kernel.pro @@ -15,6 +15,7 @@ SUBDIRS=\ qmouseevent_modal \ qpalette \ qscreen \ + qsurfaceformat \ qtouchevent \ qwindow \ qguiapplication \ diff --git a/tests/auto/gui/kernel/qsurfaceformat/qsurfaceformat.pro b/tests/auto/gui/kernel/qsurfaceformat/qsurfaceformat.pro new file mode 100644 index 0000000000..dabffde77b --- /dev/null +++ b/tests/auto/gui/kernel/qsurfaceformat/qsurfaceformat.pro @@ -0,0 +1,8 @@ +CONFIG += testcase +CONFIG += parallel_test +TARGET = tst_qsurfaceformat + +QT += core-private gui-private testlib + +SOURCES += tst_qsurfaceformat.cpp +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/gui/kernel/qsurfaceformat/tst_qsurfaceformat.cpp b/tests/auto/gui/kernel/qsurfaceformat/tst_qsurfaceformat.cpp new file mode 100644 index 0000000000..bd4fc88b3c --- /dev/null +++ b/tests/auto/gui/kernel/qsurfaceformat/tst_qsurfaceformat.cpp @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qsurfaceformat.h> + +#include <QtTest/QtTest> + +class tst_QSurfaceFormat: public QObject +{ + Q_OBJECT + +private slots: + void versionCheck_data(); + void versionCheck(); +}; + +void tst_QSurfaceFormat::versionCheck_data() +{ + QTest::addColumn<int>("formatMajor"); + QTest::addColumn<int>("formatMinor"); + QTest::addColumn<int>("compareMajor"); + QTest::addColumn<int>("compareMinor"); + QTest::addColumn<bool>("expected"); + + QTest::newRow("lower major, lower minor") + << 3 << 2 << 2 << 1 << true; + QTest::newRow("lower major, same minor") + << 3 << 2 << 2 << 2 << true; + QTest::newRow("lower major, greater minor") + << 3 << 2 << 2 << 3 << true; + QTest::newRow("same major, lower minor") + << 3 << 2 << 3 << 1 << true; + QTest::newRow("same major, same minor") + << 3 << 2 << 3 << 2 << true; + QTest::newRow("same major, greater minor") + << 3 << 2 << 3 << 3 << false; + QTest::newRow("greater major, lower minor") + << 3 << 2 << 4 << 1 << false; + QTest::newRow("greater major, same minor") + << 3 << 2 << 4 << 2 << false; + QTest::newRow("greater major, greater minor") + << 3 << 2 << 4 << 3 << false; +} + +void tst_QSurfaceFormat::versionCheck() +{ + QFETCH( int, formatMajor ); + QFETCH( int, formatMinor ); + QFETCH( int, compareMajor ); + QFETCH( int, compareMinor ); + QFETCH( bool, expected ); + + QSurfaceFormat format; + format.setMinorVersion(formatMinor); + format.setMajorVersion(formatMajor); + + QCOMPARE(format.version() >= qMakePair(compareMajor, compareMinor), expected); + + format.setVersion(formatMajor, formatMinor); + QCOMPARE(format.version() >= qMakePair(compareMajor, compareMinor), expected); +} + +#include <tst_qsurfaceformat.moc> +QTEST_MAIN(tst_QSurfaceFormat); diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp index 30666aaf2a..b67920737e 100644 --- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp +++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp @@ -49,6 +49,7 @@ // For QSignalSpy slot connections. Q_DECLARE_METATYPE(Qt::ScreenOrientation) +Q_DECLARE_METATYPE(QWindow::Visibility) class tst_QWindow: public QObject { @@ -75,6 +76,8 @@ private slots: void inputReentrancy(); void tabletEvents(); void windowModality_QTBUG27039(); + void visibility(); + void mask(); void initTestCase() { @@ -1079,6 +1082,60 @@ void tst_QWindow::windowModality_QTBUG27039() QCOMPARE(modalA.mousePressedCount, 1); } +void tst_QWindow::visibility() +{ + qRegisterMetaType<Qt::WindowModality>("QWindow::Visibility"); + + QWindow window; + QSignalSpy spy(&window, SIGNAL(visibilityChanged(QWindow::Visibility))); + + window.setVisibility(QWindow::AutomaticVisibility); + QVERIFY(window.isVisible()); + QVERIFY(window.visibility() != QWindow::Hidden); + QVERIFY(window.visibility() != QWindow::AutomaticVisibility); + QCOMPARE(spy.count(), 1); + spy.clear(); + + window.setVisibility(QWindow::Hidden); + QVERIFY(!window.isVisible()); + QCOMPARE(window.visibility(), QWindow::Hidden); + QCOMPARE(spy.count(), 1); + spy.clear(); + + window.setVisibility(QWindow::FullScreen); + QVERIFY(window.isVisible()); + QCOMPARE(window.windowState(), Qt::WindowFullScreen); + QCOMPARE(window.visibility(), QWindow::FullScreen); + QCOMPARE(spy.count(), 1); + spy.clear(); + + window.setWindowState(Qt::WindowNoState); + QCOMPARE(window.visibility(), QWindow::Windowed); + QCOMPARE(spy.count(), 1); + spy.clear(); + + window.setVisible(false); + QCOMPARE(window.visibility(), QWindow::Hidden); + QCOMPARE(spy.count(), 1); + spy.clear(); +} + +void tst_QWindow::mask() +{ + QRegion mask = QRect(10, 10, 800 - 20, 600 - 20); + + QWindow window; + window.resize(800, 600); + window.setMask(mask); + + QCOMPARE(window.mask(), QRegion()); + + window.create(); + window.setMask(mask); + + QCOMPARE(window.mask(), mask); +} + #include <tst_qwindow.moc> QTEST_MAIN(tst_QWindow) diff --git a/tests/auto/gui/painting/qpainter/qpainter.pro b/tests/auto/gui/painting/qpainter/qpainter.pro index a30564cc50..752f9be1f4 100644 --- a/tests/auto/gui/painting/qpainter/qpainter.pro +++ b/tests/auto/gui/painting/qpainter/qpainter.pro @@ -4,7 +4,6 @@ TARGET = tst_qpainter QT += testlib qtHaveModule(widgets): QT += widgets widgets-private -qtHaveModule(widgets):!wince*: QT += printsupport SOURCES += tst_qpainter.cpp diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp index cf520c06a9..2e5f43807a 100644 --- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp +++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp @@ -53,9 +53,6 @@ #include <qthread.h> #include <limits.h> #if !defined(Q_OS_WINCE) -#ifndef QT_NO_WIDGETS -#include <qprinter.h> -#endif #include <math.h> #endif #include <qpaintengine.h> diff --git a/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp b/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp index cd4f808c4e..4c73676329 100644 --- a/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp +++ b/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp @@ -154,7 +154,7 @@ void tst_QWMatrix::mapping_data() << QRect( 0, 0, 30, 40 ) << QPolygon( QRect( -300, -400, 300, 400 ) ); -#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) +#if (defined(Q_OS_WIN) || defined(Q_OS_WINCE)) && !defined(M_PI) #define M_PI 3.14159265897932384626433832795f #endif diff --git a/tests/auto/gui/qopengl/tst_qopengl.cpp b/tests/auto/gui/qopengl/tst_qopengl.cpp index 1d498773ae..97f3ec128d 100644 --- a/tests/auto/gui/qopengl/tst_qopengl.cpp +++ b/tests/auto/gui/qopengl/tst_qopengl.cpp @@ -47,6 +47,7 @@ #include <QtGui/QPainter> #include <QtGui/QScreen> #include <QtGui/QWindow> +#include <QtGui/QOffscreenSurface> #include <QtTest/QtTest> @@ -57,12 +58,18 @@ class tst_QOpenGL : public QObject Q_OBJECT private slots: + void sharedResourceCleanup_data(); void sharedResourceCleanup(); + void multiGroupSharedResourceCleanup_data(); void multiGroupSharedResourceCleanup(); + void multiGroupSharedResourceCleanupCustom_data(); void multiGroupSharedResourceCleanupCustom(); + void fboSimpleRendering_data(); void fboSimpleRendering(); + void fboRendering_data(); void fboRendering(); void fboHandleNulledAfterContextDestroyed(); + void openGLPaintDevice_data(); void openGLPaintDevice(); void aboutToBeDestroyed(); void QTBUG15621_triangulatingStrokerDivZero(); @@ -129,16 +136,43 @@ struct SharedResource : public QOpenGLSharedResource SharedResourceTracker *tracker; }; +static QSurface *createSurface(int surfaceClass) +{ + if (surfaceClass == int(QSurface::Window)) { + QWindow *window = new QWindow; + window->setSurfaceType(QWindow::OpenGLSurface); + window->setGeometry(0, 0, 10, 10); + window->create(); + return window; + } else if (surfaceClass == int(QSurface::Offscreen)) { + QOffscreenSurface *offscreenSurface = new QOffscreenSurface; + offscreenSurface->create(); + return offscreenSurface; + } + return 0; +} + +static void common_data() +{ + QTest::addColumn<int>("surfaceClass"); + + QTest::newRow("Using QWindow") << int(QSurface::Window); + QTest::newRow("Using QOffscreenSurface") << int(QSurface::Offscreen); +} + +void tst_QOpenGL::sharedResourceCleanup_data() +{ + common_data(); +} + void tst_QOpenGL::sharedResourceCleanup() { - QWindow window; - window.setSurfaceType(QWindow::OpenGLSurface); - window.setGeometry(0, 0, 10, 10); - window.create(); + QFETCH(int, surfaceClass); + QScopedPointer<QSurface> surface(createSurface(surfaceClass)); QOpenGLContext *ctx = new QOpenGLContext; ctx->create(); - ctx->makeCurrent(&window); + ctx->makeCurrent(surface.data()); SharedResourceTracker tracker; SharedResource *resource = new SharedResource(&tracker); @@ -165,7 +199,7 @@ void tst_QOpenGL::sharedResourceCleanup() QCOMPARE(tracker.freeResourceCalls, 0); QCOMPARE(tracker.destructorCalls, 0); - ctx2->makeCurrent(&window); + ctx2->makeCurrent(surface.data()); // freeResource() should now have been called QCOMPARE(tracker.invalidateResourceCalls, 0); @@ -192,17 +226,20 @@ void tst_QOpenGL::sharedResourceCleanup() QCOMPARE(tracker.destructorCalls, 1); } +void tst_QOpenGL::multiGroupSharedResourceCleanup_data() +{ + common_data(); +} + void tst_QOpenGL::multiGroupSharedResourceCleanup() { - QWindow window; - window.setSurfaceType(QWindow::OpenGLSurface); - window.setGeometry(0, 0, 10, 10); - window.create(); + QFETCH(int, surfaceClass); + QScopedPointer<QSurface> surface(createSurface(surfaceClass)); for (int i = 0; i < 10; ++i) { QOpenGLContext *gl = new QOpenGLContext(); gl->create(); - gl->makeCurrent(&window); + gl->makeCurrent(surface.data()); { // Cause QOpenGLMultiGroupSharedResource instantiation. QOpenGLFunctions func(gl); @@ -214,16 +251,19 @@ void tst_QOpenGL::multiGroupSharedResourceCleanup() // Shouldn't crash when application exits. } +void tst_QOpenGL::multiGroupSharedResourceCleanupCustom_data() +{ + common_data(); +} + void tst_QOpenGL::multiGroupSharedResourceCleanupCustom() { - QWindow window; - window.setSurfaceType(QWindow::OpenGLSurface); - window.setGeometry(0, 0, 10, 10); - window.create(); + QFETCH(int, surfaceClass); + QScopedPointer<QSurface> surface(createSurface(surfaceClass)); QOpenGLContext *ctx = new QOpenGLContext(); ctx->create(); - ctx->makeCurrent(&window); + ctx->makeCurrent(surface.data()); QOpenGLMultiGroupSharedResource multiGroupSharedResource; SharedResource *resource = multiGroupSharedResource.value<SharedResource>(ctx); @@ -350,17 +390,20 @@ void qt_opengl_check_test_pattern(const QImage& img) QFUZZY_COMPARE_PIXELS(img.pixel(192, 64), QColor(Qt::green).rgb()); } +void tst_QOpenGL::fboSimpleRendering_data() +{ + common_data(); +} void tst_QOpenGL::fboSimpleRendering() { - QWindow window; - window.setSurfaceType(QWindow::OpenGLSurface); - window.setGeometry(0, 0, 10, 10); - window.create(); + QFETCH(int, surfaceClass); + QScopedPointer<QSurface> surface(createSurface(surfaceClass)); + QOpenGLContext ctx; ctx.create(); - ctx.makeCurrent(&window); + ctx.makeCurrent(surface.data()); if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects()) QSKIP("QOpenGLFramebufferObject not supported on this platform"); @@ -386,6 +429,11 @@ void tst_QOpenGL::fboSimpleRendering() delete fbo; } +void tst_QOpenGL::fboRendering_data() +{ + common_data(); +} + // NOTE: This tests that CombinedDepthStencil attachment works by assuming the // GL2 engine is being used and is implemented the same way as it was when // this autotest was written. If this is not the case, there may be some @@ -397,14 +445,13 @@ void tst_QOpenGL::fboRendering() QSKIP("QTBUG-22617"); #endif - QWindow window; - window.setSurfaceType(QWindow::OpenGLSurface); - window.setGeometry(0, 0, 10, 10); - window.create(); + QFETCH(int, surfaceClass); + QScopedPointer<QSurface> surface(createSurface(surfaceClass)); + QOpenGLContext ctx; ctx.create(); - ctx.makeCurrent(&window); + ctx.makeCurrent(surface.data()); if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects()) QSKIP("QOpenGLFramebufferObject not supported on this platform"); @@ -461,16 +508,19 @@ void tst_QOpenGL::fboHandleNulledAfterContextDestroyed() QCOMPARE(fbo->handle(), 0U); } +void tst_QOpenGL::openGLPaintDevice_data() +{ + common_data(); +} + void tst_QOpenGL::openGLPaintDevice() { #if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(__x86_64__) QSKIP("QTBUG-22617"); #endif - QWindow window; - window.setSurfaceType(QWindow::OpenGLSurface); - window.setGeometry(0, 0, 128, 128); - window.create(); + QFETCH(int, surfaceClass); + QScopedPointer<QSurface> surface(createSurface(surfaceClass)); QOpenGLContext ctx; ctx.create(); @@ -478,7 +528,7 @@ void tst_QOpenGL::openGLPaintDevice() QSurfaceFormat format = ctx.format(); if (format.majorVersion() < 2) QSKIP("This test requires at least OpenGL 2.0"); - ctx.makeCurrent(&window); + ctx.makeCurrent(surface.data()); QImage image(128, 128, QImage::Format_RGB32); QPainter p(&image); diff --git a/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp b/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp index 15e8c2ee90..cddec5b6e7 100644 --- a/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp +++ b/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp @@ -281,7 +281,7 @@ void tst_QFontMetrics::inFontUcs4() } { - QFontEngine *engine = QFontPrivate::get(font)->engineForScript(QUnicodeTables::Common); + QFontEngine *engine = QFontPrivate::get(font)->engineForScript(QChar::Script_Common); QGlyphLayout glyphs; glyphs.numGlyphs = 3; uint buf[3]; diff --git a/tests/auto/gui/util/qregularexpressionvalidator/.gitignore b/tests/auto/gui/util/qregularexpressionvalidator/.gitignore new file mode 100644 index 0000000000..a4022144d5 --- /dev/null +++ b/tests/auto/gui/util/qregularexpressionvalidator/.gitignore @@ -0,0 +1 @@ +tst_qregularexpressionvalidator diff --git a/tests/auto/gui/util/qregularexpressionvalidator/qregularexpressionvalidator.pro b/tests/auto/gui/util/qregularexpressionvalidator/qregularexpressionvalidator.pro new file mode 100644 index 0000000000..1e8e50563e --- /dev/null +++ b/tests/auto/gui/util/qregularexpressionvalidator/qregularexpressionvalidator.pro @@ -0,0 +1,4 @@ +CONFIG += testcase parallel_test +TARGET = tst_qregularexpressionvalidator +SOURCES += tst_qregularexpressionvalidator.cpp +QT += testlib diff --git a/tests/auto/gui/util/qregularexpressionvalidator/tst_qregularexpressionvalidator.cpp b/tests/auto/gui/util/qregularexpressionvalidator/tst_qregularexpressionvalidator.cpp new file mode 100644 index 0000000000..61d26104bd --- /dev/null +++ b/tests/auto/gui/util/qregularexpressionvalidator/tst_qregularexpressionvalidator.cpp @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui/QRegularExpressionValidator> +#include <QtTest/QtTest> + +class tst_QRegularExpressionValidator : public QObject +{ + Q_OBJECT + +private slots: + void validate_data(); + void validate(); +}; + +Q_DECLARE_METATYPE(QValidator::State) + +void tst_QRegularExpressionValidator::validate_data() +{ + QTest::addColumn<QRegularExpression>("re"); + QTest::addColumn<QString>("value"); + QTest::addColumn<QValidator::State>("state"); + + QTest::newRow("data0") << QRegularExpression("[1-9]\\d{0,3}") << QString("0") << QValidator::Invalid; + QTest::newRow("data1") << QRegularExpression("[1-9]\\d{0,3}") << QString("12345") << QValidator::Invalid; + QTest::newRow("data2") << QRegularExpression("[1-9]\\d{0,3}") << QString("1") << QValidator::Acceptable; + + QTest::newRow("data3") << QRegularExpression("\\S+") << QString("myfile.txt") << QValidator::Acceptable; + QTest::newRow("data4") << QRegularExpression("\\S+") << QString("my file.txt") << QValidator::Invalid; + + QTest::newRow("data5") << QRegularExpression("[A-C]\\d{5}[W-Z]") << QString("a12345Z") << QValidator::Invalid; + QTest::newRow("data6") << QRegularExpression("[A-C]\\d{5}[W-Z]") << QString("A12345Z") << QValidator::Acceptable; + QTest::newRow("data7") << QRegularExpression("[A-C]\\d{5}[W-Z]") << QString("B12") << QValidator::Intermediate; + + QTest::newRow("data8") << QRegularExpression("read\\S?me(\\.(txt|asc|1st))?") << QString("readme") << QValidator::Acceptable; + QTest::newRow("data9") << QRegularExpression("read\\S?me(\\.(txt|asc|1st))?") << QString("read me.txt") << QValidator::Invalid; + QTest::newRow("data10") << QRegularExpression("read\\S?me(\\.(txt|asc|1st))?") << QString("readm") << QValidator::Intermediate; + + QTest::newRow("data11") << QRegularExpression("read\\S?me(\\.(txt|asc|1st))?") << QString("read me.txt") << QValidator::Invalid; + QTest::newRow("data12") << QRegularExpression("read\\S?me(\\.(txt|asc|1st))?") << QString("readm") << QValidator::Intermediate; + + QTest::newRow("data13") << QRegularExpression("\\w\\d\\d") << QString("A57") << QValidator::Acceptable; + QTest::newRow("data14") << QRegularExpression("\\w\\d\\d") << QString("E5") << QValidator::Intermediate; + QTest::newRow("data15") << QRegularExpression("\\w\\d\\d") << QString("+9") << QValidator::Invalid; + + QTest::newRow("empty01") << QRegularExpression() << QString() << QValidator::Acceptable; + QTest::newRow("empty02") << QRegularExpression() << QString("test") << QValidator::Acceptable; +} + +void tst_QRegularExpressionValidator::validate() +{ + QFETCH(QRegularExpression, re); + QFETCH(QString, value); + + QRegularExpressionValidator rv; + + // setting the same regexp won't emit signals + const int signalCount = (rv.regularExpression() == re) ? 0 : 1; + + QSignalSpy spy(&rv, SIGNAL(regularExpressionChanged(QRegularExpression))); + QSignalSpy changedSpy(&rv, SIGNAL(changed())); + + rv.setRegularExpression(re); + QCOMPARE(rv.regularExpression(), re); + + int pos = -1; + QValidator::State result = rv.validate(value, pos); + + QTEST(result, "state"); + if (result == QValidator::Invalid) + QCOMPARE(pos, value.length()); + else + QCOMPARE(pos, -1); // ensure pos is not modified if validate returned Acceptable or Intermediate + + QCOMPARE(spy.count(), signalCount); + QCOMPARE(changedSpy.count(), signalCount); +} + +QTEST_GUILESS_MAIN(tst_QRegularExpressionValidator) + +#include "tst_qregularexpressionvalidator.moc" diff --git a/tests/auto/gui/util/util.pro b/tests/auto/gui/util/util.pro index a0963980c9..f2c4515dc2 100644 --- a/tests/auto/gui/util/util.pro +++ b/tests/auto/gui/util/util.pro @@ -4,4 +4,5 @@ SUBDIRS= \ qdoublevalidator \ qintvalidator \ qregexpvalidator \ + qregularexpressionvalidator \ diff --git a/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp index 284201db29..4ee4b67ec0 100644 --- a/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp +++ b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp @@ -451,7 +451,7 @@ void tst_QNetworkCookieJar::effectiveTLDs_data() QTest::newRow("yes-wildcard1.5") << "anything.jm" << true; QTest::newRow("yes-wildcard2") << "something.kh" << true; QTest::newRow("yes-wildcard3") << "whatever.uk" << true; - QTest::newRow("yes-wildcard4") << "anything.shizuoka.jp" << true; + QTest::newRow("yes-wildcard4") << "anything.sendai.jp" << true; QTest::newRow("yes-wildcard5") << "foo.sch.uk" << true; } diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index 624ce5e800..bcc0641973 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -71,6 +71,9 @@ #ifndef QT_NO_SSL #include <QtNetwork/qsslerror.h> #include <QtNetwork/qsslconfiguration.h> +#ifdef QT_BUILD_INTERNAL +#include <QtNetwork/private/qsslconfiguration_p.h> +#endif #endif #ifndef QT_NO_BEARERMANAGEMENT #include <QtNetwork/qnetworkconfigmanager.h> @@ -173,6 +176,9 @@ public Q_SLOTS: void sslErrors(QNetworkReply*,const QList<QSslError> &); void storeSslConfiguration(); void ignoreSslErrorListSlot(QNetworkReply *reply, const QList<QSslError> &); +#ifdef QT_BUILD_INTERNAL + void sslSessionSharingHelperSlot(); +#endif #endif protected Q_SLOTS: @@ -355,8 +361,13 @@ private Q_SLOTS: void ignoreSslErrorsList(); void ignoreSslErrorsListWithSlot_data(); void ignoreSslErrorsListWithSlot(); + void encrypted(); void sslConfiguration_data(); void sslConfiguration(); +#ifdef QT_BUILD_INTERNAL + void sslSessionSharing_data(); + void sslSessionSharing(); +#endif #endif void getAndThenDeleteObject_data(); @@ -5857,6 +5868,24 @@ void tst_QNetworkReply::sslConfiguration_data() QTest::newRow("secure") << conf << true; } +void tst_QNetworkReply::encrypted() +{ + qDebug() << QtNetworkSettings::serverName(); + QUrl url("https://" + QtNetworkSettings::serverName()); + QNetworkRequest request(url); + QNetworkReply *reply = manager.get(request); + reply->ignoreSslErrors(); + + QSignalSpy spy(reply, SIGNAL(encrypted())); + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(20); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(spy.count(), 1); + + reply->deleteLater(); +} + void tst_QNetworkReply::sslConfiguration() { QNetworkRequest request(QUrl("https://" + QtNetworkSettings::serverName() + "/index.html")); @@ -5871,6 +5900,73 @@ void tst_QNetworkReply::sslConfiguration() QCOMPARE(reply->error(), expectedError); } +#ifdef QT_BUILD_INTERNAL + +void tst_QNetworkReply::sslSessionSharing_data() +{ + QTest::addColumn<bool>("sessionSharingEnabled"); + QTest::newRow("enabled") << true; + QTest::newRow("disabled") << false; +} + +void tst_QNetworkReply::sslSessionSharing() +{ + QString urlString("https://" + QtNetworkSettings::serverName()); + QList<QNetworkReplyPtr> replies; + + // warm up SSL session cache + QNetworkRequest warmupRequest(urlString); + QFETCH(bool, sessionSharingEnabled); + warmupRequest.setAttribute(QNetworkRequest::User, sessionSharingEnabled); // so we can read it from the slot + if (! sessionSharingEnabled) { + QSslConfiguration configuration(QSslConfiguration::defaultConfiguration()); + configuration.setSslOption(QSsl::SslOptionDisableSessionTickets, true); + warmupRequest.setSslConfiguration(configuration); + } + QNetworkReply *reply = manager.get(warmupRequest); + reply->ignoreSslErrors(); + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(20); + QVERIFY(!QTestEventLoop::instance().timeout()); + QCOMPARE(reply->error(), QNetworkReply::NoError); + reply->deleteLater(); + + // now send several requests at the same time, so we open more sockets and reuse the SSL session + for (int a = 0; a < 6; a++) { + QNetworkRequest request(warmupRequest); + replies.append(QNetworkReplyPtr(manager.get(request))); + connect(replies.at(a), SIGNAL(finished()), this, SLOT(sslSessionSharingHelperSlot())); + } + QTestEventLoop::instance().enterLoop(20); + QVERIFY(!QTestEventLoop::instance().timeout()); +} + +void tst_QNetworkReply::sslSessionSharingHelperSlot() +{ + static int count = 0; + + // check that SSL session sharing was used in at least one of the replies + static bool sslSessionSharingWasUsed = false; + QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender()); + bool sslSessionSharingWasUsedInReply = QSslConfigurationPrivate::peerSessionWasShared(reply->sslConfiguration()); + if (sslSessionSharingWasUsedInReply) + sslSessionSharingWasUsed = true; + + QString urlQueryString = reply->url().query(); + QCOMPARE(reply->error(), QNetworkReply::NoError); + + count++; + + if (count == 6) { // all replies have finished + QTestEventLoop::instance().exitLoop(); + bool sessionSharingWasEnabled = reply->request().attribute(QNetworkRequest::User).toBool(); + QCOMPARE(sslSessionSharingWasUsed, sessionSharingWasEnabled); + count = 0; // reset for next row + sslSessionSharingWasUsed = false; // reset for next row + } +} + +#endif // QT_BUILD_INTERNAL #endif // QT_NO_SSL void tst_QNetworkReply::getAndThenDeleteObject_data() diff --git a/tests/auto/network/ssl/qsslsocket/certs/ca.crt b/tests/auto/network/ssl/qsslsocket/certs/ca.crt new file mode 100644 index 0000000000..5cbe8ef726 --- /dev/null +++ b/tests/auto/network/ssl/qsslsocket/certs/ca.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDpTCCAl2gAwIBAgIQAKraD9BoqaSa75qOqcP7ZTANBgkqhkiG9w0BAQUFADA8 +MQswCQYDVQQGEwJHQjEZMBcGA1UEChMQV2VzdHBvaW50IENBIEtleTESMBAGA1UE +ChMJV2VzdHBvaW50MB4XDTEzMDIxNjE2NTMwOFoXDTIzMDIxNjE2NTMwOFowPDEL +MAkGA1UEBhMCR0IxGTAXBgNVBAoTEFdlc3Rwb2ludCBDQSBLZXkxEjAQBgNVBAoT +CVdlc3Rwb2ludDCCAVIwDQYJKoZIhvcNAQEBBQADggE/ADCCAToCggExAJv0H92j +WjDB9h1DmSQzt772IPSirpE82sN9ls5J19TJcPnw49LdUUqkELJkpS1ty2hYPdUw +7q3n00D+nzS+rt1QIDSKwDVoqeIyFZw4h0ULbASErfy51xBjVIr6NNoiqazp59wQ +RDvqps7of+b/NcbOh73MsiYi8T5OoI4Quv9rMBefQTAI3d2NRQ4GUzS6Hzh2INOc +4twApTDYY+yrU8IalXttIOVdKJZTHeTCdIXD3HMfHCkzyELz8rCI1/wDEp8zyoqF +/tpBStZ5LUSrlRRM7PegqcnM+aojXyrEiXBvPuqO7tabU3nsfix9+8+7GDweDXsP +OUHv+ahGNTUya7hBDaQmVk3/5hbig9kQlNiOcvcdnYYyJqiXhvjPPzOBbRaFNvBT +uG/ehHNHYsdhEBkCAwEAAaNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8E +BQMDBwYAMB0GA1UdDgQWBBSUJzi1uYQUxqb3Nr33LOLCaUUTyTANBgkqhkiG9w0B +AQUFAAOCATEAPeGh2GiIhT3cii3DU8ihd5TmnEstuHKz2FwHDChmen0zxE8lf08/ +onL1yIeaxbDA8KwZnv71/zZHJv02sPtIMUfuXQc0wOIFjDf0ngc6xIBuU7FUpLxF +2dK7g9OsiNeC7L/ZemRXgpJURdNF2Ujge9/H9yfpHFBXZztmaWir+TXc5g3PKIu6 +97t75Og+stPhTcSlph8ZHYep08b2uthCfcnuIRGeDW9LkfR8VugnuUf7GoIlqSTs +SR6bNuyTnnCHQMJzbsQ472+ag3aZS5HzoR8wyGiPmpc43lQM5ZEDrWGu8bub2gKa +/+KeqHd0wnl7Y5cxnmAptQjxvzBXX/pl4sWczesiGcYm5z5mabp4CY09Y8JtrJZT +IJodXy9ykRmEurgtRoRVc1aSp+xfV725bQ== +-----END CERTIFICATE----- diff --git a/tests/auto/network/ssl/qsslsocket/certs/inter.crt b/tests/auto/network/ssl/qsslsocket/certs/inter.crt new file mode 100644 index 0000000000..4e1d67c3e0 --- /dev/null +++ b/tests/auto/network/ssl/qsslsocket/certs/inter.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDvDCCAnSgAwIBAgIQO+uZxerYC10Ll11PBnVL4TANBgkqhkiG9w0BAQUFADA8 +MQswCQYDVQQGEwJHQjEZMBcGA1UEChMQV2VzdHBvaW50IENBIEtleTESMBAGA1UE +ChMJV2VzdHBvaW50MB4XDTEzMDIxNjE2NTMwOFoXDTIzMDIxNjE2NTMwOFowMjEL +MAkGA1UEBhMCR0IxIzAhBgNVBAoTGldlc3Rwb2ludCBJbnRlcm1lZGlhdGUgS2V5 +MIIBUjANBgkqhkiG9w0BAQEFAAOCAT8AMIIBOgKCATEAsR4tRskg2IFfQFMfGBJ1 +eqlrNejANw0oM6k5HlEB8uFA9qeyAzmflwQUPoJ55KRQ/gVHTOBdWrtgGgPMiekF +1Q36Ry1elwbAl4a+LZ6qsc9ASipvk8HirKpt1v5L9hG+aI4yDxyvjNztFtg5R4P5 +zqsh/WwhCgsYmEVfcSDbhUjqoqxGRLaZxPKO+IMCNFrjZqi0yxc8f6Un4G5SQzHA +4szi/ezcITnAFYWxHG2yaed4hawpxNS1WXabk2rzCi0pWeIcHuIczaCfZ7ElRcqV +VNNXbGTtUDlfIsh6FAVI5kTUDcPV27uf6BmHuFOu/R9Tjni25+vBFvohwQh7ZwCX +5COXnfkJLPkJQQEFVQv8nS27ht/vmyoKjERUeiuMd+hFcN5zl7bS5A2JCgi7erlP +ZQIDAQABo2QwYjAPBgNVHRMBAf8EBTADAQH/MA8GA1UdDwEB/wQFAwMHBgAwHQYD +VR0OBBYEFGn5shQ0SeTcc3x/cNu6TkoV0bPmMB8GA1UdIwQYMBaAFJQnOLW5hBTG +pvc2vfcs4sJpRRPJMA0GCSqGSIb3DQEBBQUAA4IBMQAVDS0enQQ1FL0d92xOFfwx +mjcNPz9oO7jMyEVxAs2eR2QD+xZ3Xj4gAiUEp40aGieDcLv+dg+cmuBFWF61IYSR +UyuoakVm08VDcLAwUzU+xtSvJiSSROb0GsAnVsYZj4TYlvKDplqfapOYaiIkwF+c +iE4n7G0hQW9fzqO+n3FGtBD8YUjghRqLggeRVJ2+8S3Bm8cfx8xPpRIO3ksA6opn +CORRGuzetDHihbks59mkoY3GqKFgBOyrC3kG07nv5wtKjdKDtmD/kS/SAc4fIXKy +Uruq2uXNf/1BUgF5gFGRyj22yB2D0763fJJpl5nqcLrL5RmnVObQKZGhE2VsRTV0 +untj+AmiJivhiAjjkHfw3XDf8tuL7D4pTmEkGgl5xl23fyeTIuygDCLT8fRD3ZqQ +-----END CERTIFICATE----- diff --git a/tests/auto/network/ssl/qsslsocket/certs/leaf.crt b/tests/auto/network/ssl/qsslsocket/certs/leaf.crt new file mode 100644 index 0000000000..4a7dc40540 --- /dev/null +++ b/tests/auto/network/ssl/qsslsocket/certs/leaf.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID3zCCApegAwIBAgIQEKCtd1j2bq5Gk6ND+VmKnjANBgkqhkiG9w0BAQUFADAy +MQswCQYDVQQGEwJHQjEjMCEGA1UEChMaV2VzdHBvaW50IEludGVybWVkaWF0ZSBL +ZXkwHhcNMTMwMjE2MTY1MzA4WhcNMjMwMjE2MTY1MzA4WjA1MQswCQYDVQQGEwJH +QjESMBAGA1UEChMJV2VzdHBvaW50MRIwEAYDVQQDEwkxMjcuMC4wLjEwggFSMA0G +CSqGSIb3DQEBAQUAA4IBPwAwggE6AoIBMQC7EIWIzb7XCfmQQ1KFdZ5E9f49eNK/ +KvsXYfq/iV29K1cz2hUyvfdKgyU5F/+BOPQKQ5zdWn1CraZosFv/ibuO3mhRpMfB +SfNn3rfdrE7WtA0wgT2YNIN0L4aCe+C15j2ESdmyMaFLUaUIS47JS66UtaYxp5ia +mJFO1hSNaoI0pGHyPFTTtfOza9z/01qkBbHB4htzauqs/fX5ZrnyCDSrfpVipXke +zkPKg4MkkytEkjRKw6tSXLpWIgF3ee2N/jBdefqlw8YPW08K0wmwF5qGuX6PZ8vB +sOZeWeCfVr136BopkbfP3TkGWw2BrD8xSzOUez9HVc0v4SZ/7pe5w3L4V/mzYQLt +O+1AHevCjX8+M58HYGBaWCAjxYUPGcGKcj0LLtgZgL6wY88N7RtfeOY3AgMBAAGj +gY0wgYowFAYDVR0RBA0wC4IJMTI3LjAuMC4xMAwGA1UdEwEB/wQCMAAwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDwYDVR0PAQH/BAUDAwcoADAdBgNVHQ4EFgQUKKuyJSrT +Y+dnm1do7l0sVMX96SYwHwYDVR0jBBgwFoAUafmyFDRJ5NxzfH9w27pOShXRs+Yw +DQYJKoZIhvcNAQEFBQADggExAHELijlIFdcncP3B+vxEp0SGKl0arIaCXahivb2F +VxeM3WajN6O+oDRLFltzMeDKA9RVkao7fgITzXQgCGzeNhKv0vc9iDyvR9/67vuS +W8xEEJrYowtw3VK5H1y0ewqZaxJhvKUjm4TBRWe8FGKD3s64lEsfbjOaI5VPidVc +DXmdAlXsj0Hk+v4Ej8mshPQAnVSyJ3D0ZMgTjk8Di28N0qROFIYJaTObK1rCb1nQ +GaCcmbZU6JnkYvVZ+iUe5U0GXFbb+LRNTUT8/fw1zADeHnv/G+WWVrfND+sov5Oc +33fkNE6z+n6ayABVnGLuCYhbzD38sv0dnxeh8vbykNBPzYdzPg6nw3Czv2vlhKpJ +8Yj/maoXuAyTXVf30K1/fAWyU45noq57MjQpU6UxIX1D7qw= +-----END CERTIFICATE----- diff --git a/tests/auto/network/ssl/qsslsocket/certs/leaf.key b/tests/auto/network/ssl/qsslsocket/certs/leaf.key new file mode 100644 index 0000000000..54327925d8 --- /dev/null +++ b/tests/auto/network/ssl/qsslsocket/certs/leaf.key @@ -0,0 +1,32 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIFfAIBAAKCATEAuxCFiM2+1wn5kENShXWeRPX+PXjSvyr7F2H6v4ldvStXM9oV +Mr33SoMlORf/gTj0CkOc3Vp9Qq2maLBb/4m7jt5oUaTHwUnzZ9633axO1rQNMIE9 +mDSDdC+GgnvgteY9hEnZsjGhS1GlCEuOyUuulLWmMaeYmpiRTtYUjWqCNKRh8jxU +07Xzs2vc/9NapAWxweIbc2rqrP31+Wa58gg0q36VYqV5Hs5DyoODJJMrRJI0SsOr +Uly6ViIBd3ntjf4wXXn6pcPGD1tPCtMJsBeahrl+j2fLwbDmXlngn1a9d+gaKZG3 +z905BlsNgaw/MUszlHs/R1XNL+Emf+6XucNy+Ff5s2EC7TvtQB3rwo1/PjOfB2Bg +WlggI8WFDxnBinI9Cy7YGYC+sGPPDe0bX3jmNwIDAQABAoIBMQCczBNyAStGqjjC +oHuKHHWmTh9mPWFBFfDTv6/jXmvxRWPZtaHxH2Qp09Wejqv/D9MWy2ev7spx2oZS +2Ai1ICjTbz83uAwryyW4Wen6aBTJSLCJiLstWk8ZU0DHHLjVH4FO4mwUPh95t5zC +YDr2JXbXdY8xrc5vPxUFZNJjWvR61ZK37bQYpTn5mZ7r3KfsNk2yOylRTDwa9XFo +ZZ+B82NKdrrz0UvGOnXZa5qd1ap7V+67FIAS2Mt8AMzSCG8TW0JXRUk89ISgAd8r +NQTPtX9XCnMZSbBzDKdznXfHS9ZlJcSrpsbQCPcvMVNrdBfCF0eNnsRJffJGdaXI +MsN6PvbcXWD08lXNGyeLjon03RdJnTAamNM3YQEIcjFmu5Y0o0CCJkZSCJPKJGMG +0d/1tN/5AoGZANOcOgQZ9Wiu0ej3YoQ3aSHu3y8ZBJH4B3ViX8i+2x/6UnG7KNaa +4Ygid1upnX6hk4CW5WZcoxGFacrFRpInKh5Ng8lEIHGp0VSzOBVDR0L5sAxutFuX +6N9C0CuH80vD101mOloNnfT5KHZMI5RXqP6sDGUFlwak2XybDL1qOAza3gZAy25H +vS/ll1BneBavikR5j+zxoTztAoGZAOJOJ5RyOrqpNuhiWZylah5LIFT9N1lCF4Hl +ZbFIjUZ4jcApJ7JxkMXNQ4RU/3AiKCC1xr5ib7dd/qyjKXhdMo4SnLoKhapx5R9G +3XOsQMahiCD/Zcymv9tmk8MxxzbLxhZYhEPzIP/NFkua3CHiX+d1e6fkzFLF/EiX +ZGQOgRcFKrlzUeBputRQRXAkKJH+kMClgAWvy28zAoGYKyaMXhG9DV+4xjzMBhIW +iijfsgbz+6AMRU+OIK1qmZa+ARsdNMXYf54noLVxvETOg0ZB+SGizwvZitO3lE4Q +NKWx3fTaeNMcMJ1rLkrN2UZ5M8/PT24muoAxWu8aGbURzmKuO3bTYwT7z0OvbayC +dYw36tG8/knXX6Vub6GdVGG9LKFB2nceiQnUVT0EK/wXwebYBoUvT/ECgZgF9qdG +Wyg/CPyAbS8NWLKOL86fTrjpqjsyWhgu7smCROT/XlZEdoepHrqbvx2oF85U5lVh +aPimrVxrsjUCjfoqEkV9BY/2KOAvzc9CIBTo5xLOQ8yr8uz1XCOiriogwIfsyNJb +dAm3k/D1dxQ79FowoEDs8LONrtfyFcM4e8VdFO7GSkqrDj41IBRkWx+SkVHBMdtI +yxQiTwKBmQCWym2iDCJg1ZZq4/lVwRudMhVmHoD0yoCAwADYHjjAi8QBplM0vfdd +CESKsnBhlcrPGB279BKVJyZHehKZG+/dfnFs+to14l6A3IqU2d6+pu3EyFNX34HS +xo+64QxMeF0akWnSaIPfUJfk36phjCvLBr4eLXN1i4jW3RdGFwF1THXt29VSSGmU +q/hM51H0bsQ13AIVUSdNHA== +-----END RSA PRIVATE KEY----- diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index a2bb1ec705..d1ff60ea70 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -142,6 +142,8 @@ private slots: void protocolServerSide(); void setCaCertificates(); void setLocalCertificate(); + void localCertificateChain(); + void setLocalCertificateChain(); void setPrivateKey(); void setSocketDescriptor(); void setSslConfiguration_data(); @@ -927,15 +929,20 @@ class SslServer : public QTcpServer { Q_OBJECT public: - SslServer(const QString &keyFile = SRCDIR "certs/fluke.key", const QString &certFile = SRCDIR "certs/fluke.cert") + SslServer(const QString &keyFile = SRCDIR "certs/fluke.key", + const QString &certFile = SRCDIR "certs/fluke.cert", + const QString &interFile = QString()) : socket(0), protocol(QSsl::TlsV1_0), m_keyFile(keyFile), - m_certFile(certFile) { } + m_certFile(certFile), + m_interFile(interFile) + { } QSslSocket *socket; QSsl::SslProtocol protocol; QString m_keyFile; QString m_certFile; + QString m_interFile; protected: void incomingConnection(qintptr socketDescriptor) @@ -950,10 +957,24 @@ protected: QVERIFY(!key.isNull()); socket->setPrivateKey(key); - QList<QSslCertificate> localCert = QSslCertificate::fromPath(m_certFile); - QVERIFY(!localCert.isEmpty()); - QVERIFY(localCert.first().handle()); - socket->setLocalCertificate(localCert.first()); + // If we have a cert issued directly from the CA + if (m_interFile.isEmpty()) { + QList<QSslCertificate> localCert = QSslCertificate::fromPath(m_certFile); + QVERIFY(!localCert.isEmpty()); + QVERIFY(localCert.first().handle()); + socket->setLocalCertificate(localCert.first()); + } + else { + QList<QSslCertificate> localCert = QSslCertificate::fromPath(m_certFile); + QVERIFY(!localCert.isEmpty()); + QVERIFY(localCert.first().handle()); + + QList<QSslCertificate> interCert = QSslCertificate::fromPath(m_interFile); + QVERIFY(!interCert.isEmpty()); + QVERIFY(interCert.first().handle()); + + socket->setLocalCertificateChain(localCert + interCert); + } QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState)); QVERIFY(!socket->peerAddress().isNull()); @@ -1100,6 +1121,55 @@ void tst_QSslSocket::setLocalCertificate() { } +void tst_QSslSocket::localCertificateChain() +{ + if (!QSslSocket::supportsSsl()) + return; + + QSslSocket socket; + socket.setLocalCertificate(QLatin1String(SRCDIR "certs/fluke.cert")); + + QSslConfiguration conf = socket.sslConfiguration(); + QList<QSslCertificate> chain = conf.localCertificateChain(); + QCOMPARE(chain.size(), 1); + QCOMPARE(chain[0], conf.localCertificate()); + QCOMPARE(chain[0], socket.localCertificate()); +} + +void tst_QSslSocket::setLocalCertificateChain() +{ + if (!QSslSocket::supportsSsl()) + return; + + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; + + SslServer server(QLatin1String(SRCDIR "certs/leaf.key"), + QLatin1String(SRCDIR "certs/leaf.crt"), + QLatin1String(SRCDIR "certs/inter.crt")); + + QVERIFY(server.listen()); + + QEventLoop loop; + QTimer::singleShot(5000, &loop, SLOT(quit())); + + socket = new QSslSocket(); + connect(socket, SIGNAL(encrypted()), &loop, SLOT(quit())); + connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), &loop, SLOT(quit())); + connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot())); + + socket->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort()); + loop.exec(); + + QList<QSslCertificate> chain = socket->peerCertificateChain(); + QCOMPARE(chain.size(), 2); + QCOMPARE(chain[0].serialNumber(), QByteArray("10:a0:ad:77:58:f6:6e:ae:46:93:a3:43:f9:59:8a:9e")); + QCOMPARE(chain[1].serialNumber(), QByteArray("3b:eb:99:c5:ea:d8:0b:5d:0b:97:5d:4f:06:75:4b:e1")); + + socket->deleteLater(); +} + void tst_QSslSocket::setPrivateKey() { } @@ -1533,6 +1603,8 @@ public slots: void tst_QSslSocket::setReadBufferSize_task_250027() { + QSKIP("QTBUG-29730 - flakey test blocking integration"); + // do not execute this when a proxy is set. QFETCH_GLOBAL(bool, setProxy); if (setProxy) diff --git a/tests/auto/opengl/qglbuffer/tst_qglbuffer.cpp b/tests/auto/opengl/qglbuffer/tst_qglbuffer.cpp index 475054940b..915f503b3f 100644 --- a/tests/auto/opengl/qglbuffer/tst_qglbuffer.cpp +++ b/tests/auto/opengl/qglbuffer/tst_qglbuffer.cpp @@ -202,6 +202,11 @@ void tst_QGLBuffer::testBuffer(QGLBuffer::Type type) void tst_QGLBuffer::bufferSharing() { +#if defined(Q_OS_WIN) + // Needs investigation on Windows: https://bugreports.qt-project.org/browse/QTBUG-29692 + QSKIP("Unreproducible timeout on Windows (MSVC/MinGW) CI bots"); +#endif + QGLWidget *w1 = new QGLWidget(); w1->makeCurrent(); diff --git a/tests/auto/other/lancelot/lancelot.pro b/tests/auto/other/lancelot/lancelot.pro index b577e0dbc9..ef557691e3 100644 --- a/tests/auto/other/lancelot/lancelot.pro +++ b/tests/auto/other/lancelot/lancelot.pro @@ -1,5 +1,6 @@ CONFIG += testcase CONFIG += parallel_test +CONFIG -= app_bundle TARGET = tst_lancelot QT += xml widgets testlib diff --git a/tests/auto/other/lancelot/scripts/statictext.qps b/tests/auto/other/lancelot/scripts/statictext.qps index b62b623462..c5ddda197f 100644 --- a/tests/auto/other/lancelot/scripts/statictext.qps +++ b/tests/auto/other/lancelot/scripts/statictext.qps @@ -50,7 +50,25 @@ save drawStaticText 0 80 "scaled sansserif 10pt, bold italic" restore - translate 0 100 + translate 200 200 + setPen black + save + scale -1 -1 + + setFont "sansserif" 10 normal + drawStaticText 0 20 "flipped sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawStaticText 0 40 "flipped sansserif 12pt, normal" + + setFont "sansserif" 10 bold + drawStaticText 0 60 "flipped sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawStaticText 0 80 "flipped sansserif 10pt, bold italic" + restore + + translate -200 20 setPen black save translate 200 90 @@ -91,26 +109,26 @@ restore end_block translate 250 0 -drawStaticText 25 520 "clipped to rectangle" +drawStaticText 25 640 "clipped to rectangle" save setPen #3f000000 setBrush nobrush - drawRect 20 0 100 500 - setClipRect 20 0 100 500 + drawRect 20 0 100 620 + setClipRect 20 0 100 620 setPen black repeat_block text_drawing restore translate 150 0 -drawStaticText 25 520 "clipped to path" +drawStaticText 25 640 "clipped to path" save path_moveTo clip 20 0 path_cubicTo clip 0 200 40 400 20 400 - path_lineTo clip 30 500 + path_lineTo clip 30 620 path_lineTo clip 30 0 path_lineTo clip 40 0 - path_lineTo clip 40 500 - path_lineTo clip 120 500 + path_lineTo clip 40 620 + path_lineTo clip 120 620 path_lineTo clip 120 0 path_lineTo clip 20 0 setPen #3f000000 diff --git a/tests/auto/other/lancelot/scripts/text.qps b/tests/auto/other/lancelot/scripts/text.qps index d7ee83290b..88c8690ca0 100644 --- a/tests/auto/other/lancelot/scripts/text.qps +++ b/tests/auto/other/lancelot/scripts/text.qps @@ -52,7 +52,25 @@ save drawText 0 80 "scaled sansserif 10pt, bold italic" restore - translate 0 100 + translate 200 200 + setPen black + save + scale -1 -1 + + setFont "sansserif" 10 normal + drawStaticText 0 20 "flipped sansserif 10pt, normal" + + setFont "sansserif" 12 normal + drawStaticText 0 40 "flipped sansserif 12pt, normal" + + setFont "sansserif" 10 bold + drawStaticText 0 60 "flipped sansserif 12pt, bold" + + setFont "sansserif" 10 bold italic + drawStaticText 0 80 "flipped sansserif 10pt, bold italic" + restore + + translate -200 20 setPen black save translate 200 90 @@ -93,26 +111,26 @@ restore end_block translate 250 0 -drawText 25 520 "clipped to rectangle" +drawText 25 640 "clipped to rectangle" save setPen #3f000000 setBrush nobrush - drawRect 20 0 100 500 - setClipRect 20 0 100 500 + drawRect 20 0 100 620 + setClipRect 20 0 100 620 setPen black repeat_block text_drawing restore translate 150 0 -drawText 25 520 "clipped to path" +drawText 25 640 "clipped to path" save path_moveTo clip 20 0 path_cubicTo clip 0 200 40 400 20 400 - path_lineTo clip 30 500 + path_lineTo clip 30 620 path_lineTo clip 30 0 path_lineTo clip 40 0 - path_lineTo clip 40 500 - path_lineTo clip 120 500 + path_lineTo clip 40 620 + path_lineTo clip 120 620 path_lineTo clip 120 0 path_lineTo clip 20 0 setPen #3f000000 diff --git a/tests/auto/other/other.pro b/tests/auto/other/other.pro index 35aaf4d48f..1f7582243e 100644 --- a/tests/auto/other/other.pro +++ b/tests/auto/other/other.pro @@ -42,6 +42,14 @@ SUBDIRS=\ qaccessibility \ qaccessibilitylinux \ +!qtHaveModule(network): SUBDIRS -= \ + baselineexample \ + headersclean \ + lancelot \ + networkselftest \ + qnetworkaccessmanager_and_qprogressdialog \ + qobjectperformance + testcocoon: SUBDIRS -= headersclean cross_compile: SUBDIRS -= \ diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index b0d0459326..202843f5a8 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -768,12 +768,40 @@ void tst_QAccessibility::actionTest() void tst_QAccessibility::applicationTest() { + { QLatin1String name = QLatin1String("My Name"); qApp->setApplicationName(name); - QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(qApp); + QAIPtr interface(QAccessible::queryAccessibleInterface(qApp)); QCOMPARE(interface->text(QAccessible::Name), name); + QCOMPARE(interface->text(QAccessible::Description), qApp->applicationFilePath()); + QCOMPARE(interface->text(QAccessible::Value), QString()); QCOMPARE(interface->role(), QAccessible::Application); - delete interface; + QCOMPARE(interface->window(), static_cast<QWindow*>(0)); + QCOMPARE(interface->parent(), static_cast<QAccessibleInterface*>(0)); + QCOMPARE(interface->focusChild(), static_cast<QAccessibleInterface*>(0)); + QCOMPARE(interface->indexOfChild(0), -1); + QCOMPARE(interface->child(0), static_cast<QAccessibleInterface*>(0)); + QCOMPARE(interface->child(-1), static_cast<QAccessibleInterface*>(0)); + QCOMPARE(interface->child(1), static_cast<QAccessibleInterface*>(0)); + QCOMPARE(interface->childCount(), 0); + + QWidget widget; + widget.show(); + qApp->setActiveWindow(&widget); + QVERIFY(QTest::qWaitForWindowActive(&widget)); + + QAIPtr widgetIface(QAccessible::queryAccessibleInterface(&widget)); + QCOMPARE(interface->childCount(), 1); + QAIPtr focus(interface->focusChild()); + QCOMPARE(focus->object(), &widget); + QCOMPARE(interface->indexOfChild(0), -1); + QCOMPARE(interface->indexOfChild(widgetIface.data()), 0); + QAIPtr child(interface->child(0)); + QCOMPARE(child->object(), &widget); + QCOMPARE(interface->child(-1), static_cast<QAccessibleInterface*>(0)); + QCOMPARE(interface->child(1), static_cast<QAccessibleInterface*>(0)); + } + QTestAccessibility::clearEvents(); } void tst_QAccessibility::mainWindowTest() @@ -2702,6 +2730,76 @@ void tst_QAccessibility::tableTest() QCOMPARE(table2->rowDescription(1), QString("v2")); QCOMPARE(table2->rowDescription(2), QString("v3")); + tableView->clearSelection(); + tableView->setSelectionBehavior(QAbstractItemView::SelectItems); + tableView->setSelectionMode(QAbstractItemView::SingleSelection); + QVERIFY(!table2->selectRow(0)); + QVERIFY(!table2->isRowSelected(0)); + tableView->setSelectionBehavior(QAbstractItemView::SelectRows); + QVERIFY(table2->selectRow(0)); + QVERIFY(table2->selectRow(1)); + QVERIFY(!table2->isRowSelected(0)); + tableView->setSelectionMode(QAbstractItemView::MultiSelection); + QVERIFY(table2->selectRow(0)); + QVERIFY(table2->isRowSelected(1)); + QVERIFY(table2->unselectRow(0)); + QVERIFY(!table2->isRowSelected(0)); + tableView->setSelectionBehavior(QAbstractItemView::SelectColumns); + QVERIFY(!table2->selectRow(0)); + QVERIFY(!table2->isRowSelected(0)); + tableView->clearSelection(); + QCOMPARE(table2->selectedColumnCount(), 0); + QCOMPARE(table2->selectedRowCount(), 0); + QVERIFY(table2->selectColumn(1)); + QVERIFY(table2->isColumnSelected(1)); + tableView->clearSelection(); + tableView->setSelectionMode(QAbstractItemView::ContiguousSelection); + table2->selectColumn(0); + table2->selectColumn(2); + QVERIFY(!(table2->isColumnSelected(2) && table2->isColumnSelected(0))); + tableView->clearSelection(); + tableView->setSelectionBehavior(QAbstractItemView::SelectItems); + tableView->setSelectionMode(QAbstractItemView::MultiSelection); + table2->selectColumn(1); + table2->selectRow(1); + QVERIFY(table2->isColumnSelected(1)); + QVERIFY(table2->isRowSelected(1)); + + QAIPtr cell4(table2->cellAt(2,2)); + QVERIFY(cell1->actionInterface()); + QVERIFY(cell1->tableCellInterface()); + + tableView->clearSelection(); + tableView->setSelectionBehavior(QAbstractItemView::SelectRows); + tableView->setSelectionMode(QAbstractItemView::SingleSelection); + QVERIFY(!cell1->tableCellInterface()->isSelected()); + QVERIFY(cell1->actionInterface()->actionNames().contains(QAccessibleActionInterface::toggleAction())); + cell1->actionInterface()->doAction(QAccessibleActionInterface::toggleAction()); + QVERIFY(cell2->tableCellInterface()->isSelected()); + + tableView->clearSelection(); + tableView->setSelectionBehavior(QAbstractItemView::SelectColumns); + cell3->actionInterface()->doAction(QAccessibleActionInterface::toggleAction()); + QVERIFY(cell4->tableCellInterface()->isSelected()); + + tableView->clearSelection(); + tableView->setSelectionBehavior(QAbstractItemView::SelectItems); + tableView->setSelectionMode(QAbstractItemView::SingleSelection); + cell1->actionInterface()->doAction(QAccessibleActionInterface::toggleAction()); + QVERIFY(cell1->tableCellInterface()->isSelected()); + cell2->actionInterface()->doAction(QAccessibleActionInterface::toggleAction()); + QVERIFY(!cell1->tableCellInterface()->isSelected()); + + tableView->clearSelection(); + tableView->setSelectionMode(QAbstractItemView::MultiSelection); + cell1->actionInterface()->doAction(QAccessibleActionInterface::toggleAction()); + cell2->actionInterface()->doAction(QAccessibleActionInterface::toggleAction()); + QVERIFY(cell1->tableCellInterface()->isSelected()); + QVERIFY(cell2->tableCellInterface()->isSelected()); + cell2->actionInterface()->doAction(QAccessibleActionInterface::toggleAction()); + QVERIFY(cell1->tableCellInterface()->isSelected()); + QVERIFY(!cell2->tableCellInterface()->isSelected()); + delete tableView; QTestAccessibility::clearEvents(); diff --git a/tests/auto/sql/kernel/qsqlresult/testsqldriver.h b/tests/auto/sql/kernel/qsqlresult/testsqldriver.h index 7040ddf360..9d435a0f7c 100644 --- a/tests/auto/sql/kernel/qsqlresult/testsqldriver.h +++ b/tests/auto/sql/kernel/qsqlresult/testsqldriver.h @@ -86,6 +86,8 @@ public: case QSqlDriver::PreparedQueries: case QSqlDriver::NamedPlaceholders: return true; + default: + break; } return false; } diff --git a/tests/auto/test.pl b/tests/auto/test.pl index 568dbeec54..9340299a8d 100755 --- a/tests/auto/test.pl +++ b/tests/auto/test.pl @@ -42,6 +42,7 @@ use strict; use Cwd; +use warnings; # Usage: test.pl <SearchPath> <ExecutionMode> <TestResults> <Timeout [Default 300 seconds]> # Variable declarations to keep strict happy @@ -56,8 +57,8 @@ our $timeoutChildren; our $totalExecuted; our $totalStarted; our $totalTimedOut; -our $next; our $currentDirectory; +our $testRoot; # Where do we run this script? What directory? $SEARCH_PATH=$ARGV[0]; @@ -86,8 +87,8 @@ if($EXEC_MODE =~ /^U$/) } elsif($EXEC_MODE =~ /^M$/) { print "Using OSX execution mode\n"; - $EXE_PREFIX="/Content/MacOS/"; - $EXE_SUFFIX=""; + $EXE_PREFIX="/Contents/MacOS/"; + $EXE_SUFFIX=".app"; } elsif($EXEC_MODE =~ /^E$/) { print "Using embedded execution mode\n"; @@ -101,24 +102,18 @@ if($EXEC_MODE =~ /^U$/) # We get the current directory, we 'll need it afterwards $currentDirectory = getcwd(); +$testRoot = Cwd::abs_path($SEARCH_PATH); + # We assume that by default goes to "reports" unless the user specifies it. $REPORTDIR = $ARGV[2]; if(!$REPORTDIR) { - if($SEARCH_PATH =~ /^\.$/) - { -# '.' ie current directory - $REPORTDIR = $currentDirectory."/reports"; - } elsif($SEARCH_PATH =~ /^\//) { -# Absolute path - $REPORTDIR = $SEARCH_PATH."/reports"; - } else { -# Relative path - $REPORTDIR = $currentDirectory.$SEARCH_PATH."/reports"; - } + $REPORTDIR = $testRoot."/reports"; + mkdir $REPORTDIR; +} else { + mkdir $REPORTDIR; + $REPORTDIR = Cwd::abs_path($REPORTDIR); } -# Let's create the directory -mkdir $REPORTDIR; # If given we use it, otherwise we default to 300 seconds. $TIMEOUT = $ARGV[3]; @@ -139,23 +134,51 @@ $totalTimedOut = 0; $SIG{'CHLD'} = 'handleDeath'; $SIG{'ALRM'} = 'handleTimeout'; -while ($next = <$SEARCH_PATH/*>) -{ - if( -d $next ) +handleDir($testRoot); + +print " ** Statistics ** \n"; +print " Tests started: $totalStarted \n"; +print " Tests executed: $totalExecuted \n"; +print " Tests timed out: $totalTimedOut \n"; + +sub handleDir { + + my ($dir) = @_; + my $currentDir = getcwd(); + + chdir($dir) || die("Could not chdir to $dir"); + my @components; + my $command; + @components = split(/\//, $dir); + my $component = $components[$#components]; + + $command = "tst_".$component; + + if ( -e $command.$EXE_SUFFIX ) { - print "Examining $next \n"; - chdir($next) || die("Could not chdir to $next"); - my @components; - my $command; - @components = split(/\//, $next); - if($EXEC_MODE =~ /^M$/) + executeTestCurrentDir($command); + } else { + opendir(DIR, $dir); + my @files = readdir(DIR); + closedir DIR; + my $file; + foreach $file (@files) { - $command = "tst_".$components[1].".app"; - } else { - $command = "tst_".$components[1]; + #skip hidden files + next if (substr($file,0,1) eq "."); + + if ( -d $dir."/".$file) + { + handleDir($dir."/".$file) + } + } - if( -e $command) - { + } + chdir($currentDir); +} + +sub executeTestCurrentDir { + my ($command) = @_; print "Executing $command \n"; my $myPid; $myPid = fork(); @@ -164,11 +187,12 @@ while ($next = <$SEARCH_PATH/*>) my $realCommand; if($EXEC_MODE =~/^M$/) { - $realCommand = "./".$command.".app".$EXE_PREFIX.$command; + $realCommand = "./".$command.$EXE_SUFFIX.$EXE_PREFIX.$command; } else { $realCommand = $EXE_PREFIX.$command.$EXE_SUFFIX; } - my $outputRedirection = $REPORTDIR."/".$command.".xml"; + my $outputRedirection = $REPORTDIR."/".$command.$EXE_SUFFIX.".xml"; + if($EXEC_MODE =~ /^E$/) { exec($realCommand, "-qws", "-xml", "-o", $outputRedirection); @@ -210,15 +234,8 @@ while ($next = <$SEARCH_PATH/*>) } else { print "Problems trying to execute $command"; } - } - } - chdir($currentDirectory); } -print " ** Statistics ** \n"; -print " Tests started: $totalStarted \n"; -print " Tests executed: $totalExecuted \n"; -print " Tests timed out: $totalTimedOut \n"; # This procedure takes care of handling dead children on due time sub handleDeath { diff --git a/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp b/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp index 6506479d1d..e9ad1778fa 100644 --- a/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp +++ b/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp @@ -136,6 +136,8 @@ private slots: void compare_tostring_data(); void compareQStringLists(); void compareQStringLists_data(); + void compareQListInt(); + void compareQListDouble(); void compareQPixmaps(); void compareQPixmaps_data(); void compareQImages(); @@ -307,6 +309,20 @@ void tst_Cmptest::compareQStringLists() QCOMPARE(opA, opB); } +void tst_Cmptest::compareQListInt() +{ + QList<int> int1; int1 << 1 << 2 << 3; + QList<int> int2; int2 << 1 << 2 << 4; + QCOMPARE(int1, int2); +} + +void tst_Cmptest::compareQListDouble() +{ + QList<double> double1; double1 << 1.5 << 2 << 3; + QList<double> double2; double2 << 1 << 2 << 4; + QCOMPARE(double1, double2); +} + void tst_Cmptest::compareQPixmaps_data() { QTest::addColumn<QPixmap>("opA"); diff --git a/tests/auto/testlib/selftests/expected_cmptest.lightxml b/tests/auto/testlib/selftests/expected_cmptest.lightxml index 83b2e6e137..54c5bb85f0 100644 --- a/tests/auto/testlib/selftests/expected_cmptest.lightxml +++ b/tests/auto/testlib/selftests/expected_cmptest.lightxml @@ -49,35 +49,49 @@ </Incident> <Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="308"> <DataTag><![CDATA[last item different]]></DataTag> - <Description><![CDATA[Compared QStringLists differ at index 2. + <Description><![CDATA[Compared lists differ at index 2. Actual (opA): 'string3' Expected (opB): 'DIFFERS']]></Description> </Incident> <Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="308"> <DataTag><![CDATA[second-last item different]]></DataTag> - <Description><![CDATA[Compared QStringLists differ at index 2. + <Description><![CDATA[Compared lists differ at index 2. Actual (opA): 'string3' Expected (opB): 'DIFFERS']]></Description> </Incident> <Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="308"> <DataTag><![CDATA[prefix]]></DataTag> - <Description><![CDATA[Compared QStringLists have different sizes. + <Description><![CDATA[Compared lists have different sizes. Actual (opA) size: '2' Expected (opB) size: '1']]></Description> </Incident> <Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="308"> <DataTag><![CDATA[short list second]]></DataTag> - <Description><![CDATA[Compared QStringLists have different sizes. + <Description><![CDATA[Compared lists have different sizes. Actual (opA) size: '12' Expected (opB) size: '1']]></Description> </Incident> <Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="308"> <DataTag><![CDATA[short list first]]></DataTag> - <Description><![CDATA[Compared QStringLists have different sizes. + <Description><![CDATA[Compared lists have different sizes. Actual (opA) size: '1' Expected (opB) size: '12']]></Description> </Incident> </TestFunction> +<TestFunction name="compareQListInt"> +<Incident type="fail" file="tst_cmptest.cpp" line="316"> + <Description><![CDATA[Compared lists differ at index 2. + Actual (int1): '3' + Expected (int2): '4']]></Description> +</Incident> +</TestFunction> +<TestFunction name="compareQListDouble"> +<Incident type="fail" file="tst_cmptest.cpp" line="323"> + <Description><![CDATA[Compared lists differ at index 0. + Actual (double1): '1.5' + Expected (double2): '1']]></Description> +</Incident> +</TestFunction> <TestFunction name="compareQPixmaps"> <Incident type="pass" file="" line="0"> <DataTag><![CDATA[both null]]></DataTag> diff --git a/tests/auto/testlib/selftests/expected_cmptest.txt b/tests/auto/testlib/selftests/expected_cmptest.txt index de666ed8b1..d41da53b06 100644 --- a/tests/auto/testlib/selftests/expected_cmptest.txt +++ b/tests/auto/testlib/selftests/expected_cmptest.txt @@ -22,26 +22,34 @@ FAIL! : tst_Cmptest::compare_tostring(both non-null user type) Compared values Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(214)] PASS : tst_Cmptest::compareQStringLists(empty lists) PASS : tst_Cmptest::compareQStringLists(equal lists) -FAIL! : tst_Cmptest::compareQStringLists(last item different) Compared QStringLists differ at index 2. +FAIL! : tst_Cmptest::compareQStringLists(last item different) Compared lists differ at index 2. Actual (opA): 'string3' Expected (opB): 'DIFFERS' Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(308)] -FAIL! : tst_Cmptest::compareQStringLists(second-last item different) Compared QStringLists differ at index 2. +FAIL! : tst_Cmptest::compareQStringLists(second-last item different) Compared lists differ at index 2. Actual (opA): 'string3' Expected (opB): 'DIFFERS' Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(308)] -FAIL! : tst_Cmptest::compareQStringLists(prefix) Compared QStringLists have different sizes. +FAIL! : tst_Cmptest::compareQStringLists(prefix) Compared lists have different sizes. Actual (opA) size: '2' Expected (opB) size: '1' Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(308)] -FAIL! : tst_Cmptest::compareQStringLists(short list second) Compared QStringLists have different sizes. +FAIL! : tst_Cmptest::compareQStringLists(short list second) Compared lists have different sizes. Actual (opA) size: '12' Expected (opB) size: '1' Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(308)] -FAIL! : tst_Cmptest::compareQStringLists(short list first) Compared QStringLists have different sizes. +FAIL! : tst_Cmptest::compareQStringLists(short list first) Compared lists have different sizes. Actual (opA) size: '1' Expected (opB) size: '12' Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(308)] +FAIL! : tst_Cmptest::compareQListInt() Compared lists differ at index 2. + Actual (int1): '3' + Expected (int2): '4' + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(316)] +FAIL! : tst_Cmptest::compareQListDouble() Compared lists differ at index 0. + Actual (double1): '1.5' + Expected (double2): '1' + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(323)] PASS : tst_Cmptest::compareQPixmaps(both null) FAIL! : tst_Cmptest::compareQPixmaps(one null) Compared QPixmaps differ. Actual (opA).isNull(): 1 @@ -79,5 +87,5 @@ FAIL! : tst_Cmptest::compareQImages(different format) Compared QImages differ i FAIL! : tst_Cmptest::compareQImages(different pixels) Compared values are not the same Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(360)] PASS : tst_Cmptest::cleanupTestCase() -Totals: 11 passed, 18 failed, 0 skipped +Totals: 11 passed, 20 failed, 0 skipped ********* Finished testing of tst_Cmptest ********* diff --git a/tests/auto/testlib/selftests/expected_cmptest.xml b/tests/auto/testlib/selftests/expected_cmptest.xml index 0e5b6de335..ccab93d7c0 100644 --- a/tests/auto/testlib/selftests/expected_cmptest.xml +++ b/tests/auto/testlib/selftests/expected_cmptest.xml @@ -51,35 +51,49 @@ </Incident> <Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="308"> <DataTag><![CDATA[last item different]]></DataTag> - <Description><![CDATA[Compared QStringLists differ at index 2. + <Description><![CDATA[Compared lists differ at index 2. Actual (opA): 'string3' Expected (opB): 'DIFFERS']]></Description> </Incident> <Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="308"> <DataTag><![CDATA[second-last item different]]></DataTag> - <Description><![CDATA[Compared QStringLists differ at index 2. + <Description><![CDATA[Compared lists differ at index 2. Actual (opA): 'string3' Expected (opB): 'DIFFERS']]></Description> </Incident> <Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="308"> <DataTag><![CDATA[prefix]]></DataTag> - <Description><![CDATA[Compared QStringLists have different sizes. + <Description><![CDATA[Compared lists have different sizes. Actual (opA) size: '2' Expected (opB) size: '1']]></Description> </Incident> <Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="308"> <DataTag><![CDATA[short list second]]></DataTag> - <Description><![CDATA[Compared QStringLists have different sizes. + <Description><![CDATA[Compared lists have different sizes. Actual (opA) size: '12' Expected (opB) size: '1']]></Description> </Incident> <Incident type="fail" file="/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="308"> <DataTag><![CDATA[short list first]]></DataTag> - <Description><![CDATA[Compared QStringLists have different sizes. + <Description><![CDATA[Compared lists have different sizes. Actual (opA) size: '1' Expected (opB) size: '12']]></Description> </Incident> </TestFunction> +<TestFunction name="compareQListInt"> +<Incident type="fail" file="tst_cmptest.cpp" line="316"> + <Description><![CDATA[Compared lists differ at index 2. + Actual (int1): '3' + Expected (int2): '4']]></Description> +</Incident> +</TestFunction> +<TestFunction name="compareQListDouble"> +<Incident type="fail" file="tst_cmptest.cpp" line="323"> + <Description><![CDATA[Compared lists differ at index 0. + Actual (double1): '1.5' + Expected (double2): '1']]></Description> +</Incident> +</TestFunction> <TestFunction name="compareQPixmaps"> <Incident type="pass" file="" line="0"> <DataTag><![CDATA[both null]]></DataTag> diff --git a/tests/auto/testlib/selftests/expected_cmptest.xunitxml b/tests/auto/testlib/selftests/expected_cmptest.xunitxml index 33e78a5290..0cb88147b0 100644 --- a/tests/auto/testlib/selftests/expected_cmptest.xunitxml +++ b/tests/auto/testlib/selftests/expected_cmptest.xunitxml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<testsuite errors="0" failures="18" tests="8" name="tst_Cmptest"> +<testsuite errors="0" failures="20" tests="10" name="tst_Cmptest"> <properties> <property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/> <property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/> @@ -22,22 +22,32 @@ Expected (expected): QVariant(PhonyClass,<value not representable as string>)" result="fail"/> </testcase> <testcase result="fail" name="compareQStringLists"> - <failure tag="last item different" message="Compared QStringLists differ at index 2. + <failure tag="last item different" message="Compared lists differ at index 2. Actual (opA): 'string3' Expected (opB): 'DIFFERS'" result="fail"/> - <failure tag="second-last item different" message="Compared QStringLists differ at index 2. + <failure tag="second-last item different" message="Compared lists differ at index 2. Actual (opA): 'string3' Expected (opB): 'DIFFERS'" result="fail"/> - <failure tag="prefix" message="Compared QStringLists have different sizes. + <failure tag="prefix" message="Compared lists have different sizes. Actual (opA) size: '2' Expected (opB) size: '1'" result="fail"/> - <failure tag="short list second" message="Compared QStringLists have different sizes. + <failure tag="short list second" message="Compared lists have different sizes. Actual (opA) size: '12' Expected (opB) size: '1'" result="fail"/> - <failure tag="short list first" message="Compared QStringLists have different sizes. + <failure tag="short list first" message="Compared lists have different sizes. Actual (opA) size: '1' Expected (opB) size: '12'" result="fail"/> </testcase> + <testcase result="fail" name="compareQListInt"> + <failure message="Compared lists differ at index 2. + Actual (int1): '3' + Expected (int2): '4'" result="fail"/> + </testcase> + <testcase result="fail" name="compareQListDouble"> + <failure message="Compared lists differ at index 0. + Actual (double1): '1.5' + Expected (double2): '1'" result="fail"/> + </testcase> <testcase result="fail" name="compareQPixmaps"> <failure tag="one null" message="Compared QPixmaps differ. Actual (opA).isNull(): 1 diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp index 4b19ee57ea..441254c126 100644 --- a/tests/auto/testlib/selftests/tst_selftests.cpp +++ b/tests/auto/testlib/selftests/tst_selftests.cpp @@ -563,6 +563,9 @@ void tst_Selftests::doRunSubTest(QString const& subdir, QStringList const& logge && subdir != QLatin1String("cmptest") // QImage comparison requires QGuiApplication && subdir != QLatin1String("fetchbogus") && subdir != QLatin1String("xunit") +#ifdef Q_CC_MINGW + && subdir != QLatin1String("silent") // calls qFatal() +#endif && subdir != QLatin1String("benchlibcallgrind")) QVERIFY2(err.isEmpty(), err.constData()); @@ -570,8 +573,8 @@ void tst_Selftests::doRunSubTest(QString const& subdir, QStringList const& logge QString logger = loggers[n]; QList<QByteArray> res = splitLines(actualOutputs[n]); QList<QByteArray> exp = expectedResult(subdir, logger); -#ifdef Q_CC_MSVC - // MSVC formats double numbers differently +#if defined (Q_CC_MSVC) || defined(Q_CC_MINGW) + // MSVC, MinGW format double numbers differently if (n == 0 && subdir == QStringLiteral("float")) { for (int i = 0; i < exp.size(); ++i) { exp[i].replace("e-07", "e-007"); diff --git a/tests/auto/tools/moc/dollars.h b/tests/auto/tools/moc/dollars.h new file mode 100644 index 0000000000..8fab45559c --- /dev/null +++ b/tests/auto/tools/moc/dollars.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* both GCC and clang allow $ in identifiers + * So moc should not throw a parse error if it parses a file that contains such identifiers + */ + +#include <QObject> + +#define macro$1 function1 +#define $macro2 function2 + +namespace $NS { + class $CLS : public QObject + { + Q_PROPERTY(int rich$ MEMBER m_$rich$) + Q_PROPERTY(int money$$$ READ $$$money$$$ WRITE $$$setMoney$$$) + Q_OBJECT + + int m_$rich$; + int m_money; + int $$$money$$$() { return m_money; } + int $$$setMoney$$$(int m) { return m_money = m; } + + Q_SIGNALS: + void macro$1 (); + void $macro2 (); + + void function$3 ($CLS * cl$s); + }; +} + diff --git a/tests/auto/tools/moc/moc.pro b/tests/auto/tools/moc/moc.pro index 772086d3c4..1600c458b5 100644 --- a/tests/auto/tools/moc/moc.pro +++ b/tests/auto/tools/moc/moc.pro @@ -11,7 +11,6 @@ TARGET = tst_moc INCLUDEPATH += testproject/include testproject -DEFINES += SRCDIR=\\\"$$PWD\\\" cross_compile: DEFINES += MOC_CROSS_COMPILED HEADERS += using-namespaces.h no-keywords.h task87883.h c-comments.h backslash-newlines.h oldstyle-casts.h \ @@ -27,6 +26,7 @@ HEADERS += using-namespaces.h no-keywords.h task87883.h c-comments.h backslash-n if(*-g++*|*-icc*|*-clang*|*-llvm):!irix-*:!win32-*: HEADERS += os9-newlines.h win-newlines.h +if(*-g++*|*-clang*): HEADERS += dollars.h SOURCES += tst_moc.cpp QT -= gui diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index ee82dc0652..5fc46d195b 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com> ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. @@ -447,15 +448,6 @@ public: #endif #endif -static QString srcify(const char *path) -{ -#ifndef Q_OS_IRIX - return QString(SRCDIR) + QLatin1Char('/') + QLatin1String(path); -#else - return QString(QLatin1String(path)); -#endif -} - class CtorTestClass : public QObject { Q_OBJECT @@ -480,6 +472,8 @@ CtorTestClass::CtorTestClass(QObject *parent) CtorTestClass::CtorTestClass(int, int, int) {} +class PrivatePropertyTest; + class tst_Moc : public QObject { Q_OBJECT @@ -487,9 +481,15 @@ class tst_Moc : public QObject Q_PROPERTY(bool user1 READ user1 USER true ) Q_PROPERTY(bool user2 READ user2 USER false) Q_PROPERTY(bool user3 READ user3 USER userFunction()) + Q_PROPERTY(QString member1 MEMBER sMember) + Q_PROPERTY(QString member2 MEMBER sMember READ member2) + Q_PROPERTY(QString member3 MEMBER sMember WRITE setMember3) + Q_PROPERTY(QString member4 MEMBER sMember NOTIFY member4Changed) + Q_PROPERTY(QString member5 MEMBER sMember NOTIFY member5Changed) + Q_PROPERTY(QString member6 MEMBER sConst CONSTANT) public: - inline tst_Moc() {} + inline tst_Moc() : sConst("const") {} private slots: void initTestCase(); @@ -546,6 +546,9 @@ private slots: void cxx11Enums_data(); void cxx11Enums(); void returnRefs(); + void memberProperties_data(); + void memberProperties(); + void memberProperties2(); void privateSignalConnection(); void finalClasses_data(); void finalClasses(); @@ -553,6 +556,7 @@ private slots: void explicitOverrideControl(); void autoPropertyMetaTypeRegistration(); void autoMethodArgumentMetaTypeRegistration(); + void autoSignalSpyMetaTypeRegistration(); void parseDefines(); void preprocessorOnly(); void unterminatedFunctionMacro(); @@ -565,6 +569,8 @@ signals: void sigWithCustomType(const MyStruct); void constSignal1() const; void constSignal2(int arg) const; + void member4Changed(); + void member5Changed(const QString &newVal); private: bool user1() { return true; }; @@ -572,14 +578,23 @@ private: bool user3() { return false; }; bool userFunction(){ return false; }; template <class T> void revisions_T(); + QString member2() const { return sMember; } + void setMember3( const QString &sVal ) { sMember = sVal; } private: + QString m_sourceDirectory; QString qtIncludePath; class PrivateClass; + QString sMember; + const QString sConst; + PrivatePropertyTest *pPPTest; }; void tst_Moc::initTestCase() { + const QString testHeader = QFINDTESTDATA("backslash-newlines.h"); + QVERIFY(!testHeader.isEmpty()); + m_sourceDirectory = QFileInfo(testHeader).absolutePath(); #if defined(Q_OS_UNIX) && !defined(QT_NO_PROCESS) QProcess proc; proc.start("qmake", QStringList() << "-query" << "QT_INSTALL_HEADERS"); @@ -626,7 +641,7 @@ void tst_Moc::oldStyleCasts() #endif #if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; - proc.start("moc", QStringList(srcify("/oldstyle-casts.h"))); + proc.start("moc", QStringList(m_sourceDirectory + QStringLiteral("/oldstyle-casts.h"))); QVERIFY(proc.waitForFinished()); QCOMPARE(proc.exitCode(), 0); QByteArray mocOut = proc.readAllStandardOutput(); @@ -656,15 +671,16 @@ void tst_Moc::warnOnExtraSignalSlotQualifiaction() #endif #if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; - proc.start("moc", QStringList(srcify("extraqualification.h"))); + const QString header = m_sourceDirectory + QStringLiteral("/extraqualification.h"); + proc.start("moc", QStringList(header)); QVERIFY(proc.waitForFinished()); QCOMPARE(proc.exitCode(), 0); QByteArray mocOut = proc.readAllStandardOutput(); QVERIFY(!mocOut.isEmpty()); QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError()); - QCOMPARE(mocWarning, QString(SRCDIR) + - QString("/extraqualification.h:53: Warning: Function declaration Test::badFunctionDeclaration contains extra qualification. Ignoring as signal or slot.\n") + - QString(SRCDIR) + QString("/extraqualification.h:56: Warning: parsemaybe: Function declaration Test::anotherOne contains extra qualification. Ignoring as signal or slot.\n")); + QCOMPARE(mocWarning, header + + QString(":53: Warning: Function declaration Test::badFunctionDeclaration contains extra qualification. Ignoring as signal or slot.\n") + + header + QString(":56: Warning: parsemaybe: Function declaration Test::anotherOne contains extra qualification. Ignoring as signal or slot.\n")); #else QSKIP("Only tested on linux/gcc"); #endif @@ -694,7 +710,7 @@ void tst_Moc::inputFileNameWithDotsButNoExtension() #endif #if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; - proc.setWorkingDirectory(QString(SRCDIR) + "/task71021"); + proc.setWorkingDirectory(m_sourceDirectory + QStringLiteral("/task71021")); proc.start("moc", QStringList("../Header")); QVERIFY(proc.waitForFinished()); QCOMPARE(proc.exitCode(), 0); @@ -933,16 +949,16 @@ void tst_Moc::warnOnMultipleInheritance() #if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; QStringList args; - args << "-I" << qtIncludePath + "/QtGui" - << srcify("warn-on-multiple-qobject-subclasses.h"); + const QString header = m_sourceDirectory + QStringLiteral("/warn-on-multiple-qobject-subclasses.h"); + args << "-I" << qtIncludePath + "/QtGui" << header; proc.start("moc", args); QVERIFY(proc.waitForFinished()); QCOMPARE(proc.exitCode(), 0); QByteArray mocOut = proc.readAllStandardOutput(); QVERIFY(!mocOut.isEmpty()); QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError()); - QCOMPARE(mocWarning, QString(SRCDIR) + - QString("/warn-on-multiple-qobject-subclasses.h:53: Warning: Class Bar inherits from two QObject subclasses QWindow and Foo. This is not supported!\n")); + QCOMPARE(mocWarning, header + + QString(":53: Warning: Class Bar inherits from two QObject subclasses QWindow and Foo. This is not supported!\n")); #else QSKIP("Only tested on linux/gcc"); #endif @@ -956,16 +972,16 @@ void tst_Moc::forgottenQInterface() #if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; QStringList args; - args << "-I" << qtIncludePath + "/QtCore" - << srcify("forgotten-qinterface.h"); + const QString header = m_sourceDirectory + QStringLiteral("/forgotten-qinterface.h"); + args << "-I" << qtIncludePath + "/QtCore" << header; proc.start("moc", args); QVERIFY(proc.waitForFinished()); QCOMPARE(proc.exitCode(), 0); QByteArray mocOut = proc.readAllStandardOutput(); QVERIFY(!mocOut.isEmpty()); QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError()); - QCOMPARE(mocWarning, QString(SRCDIR) + - QString("/forgotten-qinterface.h:55: Warning: Class Test implements the interface MyInterface but does not list it in Q_INTERFACES. qobject_cast to MyInterface will not work!\n")); + QCOMPARE(mocWarning, header + + QString(":55: Warning: Class Test implements the interface MyInterface but does not list it in Q_INTERFACES. qobject_cast to MyInterface will not work!\n")); #else QSKIP("Only tested on linux/gcc"); #endif @@ -976,7 +992,7 @@ void tst_Moc::os9Newline() #if !defined(SKIP_NEWLINE_TEST) const QMetaObject &mo = Os9Newlines::staticMetaObject; QVERIFY(mo.indexOfSlot("testSlot()") != -1); - QFile f(srcify("os9-newlines.h")); + QFile f(m_sourceDirectory + QStringLiteral("/os9-newlines.h")); QVERIFY(f.open(QIODevice::ReadOnly)); // no QIODevice::Text! QByteArray data = f.readAll(); f.close(); @@ -990,7 +1006,7 @@ void tst_Moc::winNewline() #if !defined(SKIP_NEWLINE_TEST) const QMetaObject &mo = WinNewlines::staticMetaObject; QVERIFY(mo.indexOfSlot("testSlot()") != -1); - QFile f(srcify("win-newlines.h")); + QFile f(m_sourceDirectory + QStringLiteral("/win-newlines.h")); QVERIFY(f.open(QIODevice::ReadOnly)); // no QIODevice::Text! QByteArray data = f.readAll(); f.close(); @@ -1037,8 +1053,8 @@ void tst_Moc::frameworkSearchPath() #endif #if defined(Q_OS_UNIX) && !defined(QT_NO_PROCESS) QStringList args; - args << "-F" << srcify(".") - << srcify("interface-from-framework.h") + args << "-F" << m_sourceDirectory + QStringLiteral("/.") + << m_sourceDirectory + QStringLiteral("/interface-from-framework.h") ; QProcess proc; @@ -1075,7 +1091,7 @@ void tst_Moc::templateGtGt() #endif #if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; - proc.start("moc", QStringList(srcify("template-gtgt.h"))); + proc.start("moc", QStringList(m_sourceDirectory + QStringLiteral("/template-gtgt.h"))); QVERIFY(proc.waitForFinished()); QCOMPARE(proc.exitCode(), 0); QByteArray mocOut = proc.readAllStandardOutput(); @@ -1094,7 +1110,7 @@ void tst_Moc::defineMacroViaCmdline() QStringList args; args << "-DFOO"; - args << srcify("macro-on-cmdline.h"); + args << m_sourceDirectory + QStringLiteral("/macro-on-cmdline.h"); proc.start("moc", args); QVERIFY(proc.waitForFinished()); @@ -1164,25 +1180,38 @@ class PrivatePropertyTest : public QObject Q_PRIVATE_PROPERTY(d, int bar READ bar WRITE setBar) Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, int plop READ plop WRITE setPlop) Q_PRIVATE_PROPERTY(PrivatePropertyTest::d_func(), int baz READ baz WRITE setBaz) + Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub MEMBER mBlub) + Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub2 MEMBER mBlub READ blub) + Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub3 MEMBER mBlub WRITE setBlub) + Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub4 MEMBER mBlub NOTIFY blub4Changed) + Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub5 MEMBER mBlub NOTIFY blub5Changed) + Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, QString blub6 MEMBER mConst CONSTANT) class MyDPointer { public: - MyDPointer() : mBar(0), mPlop(0) {} + MyDPointer() : mConst("const"), mBar(0), mPlop(0) {} int bar() { return mBar ; } void setBar(int value) { mBar = value; } int plop() { return mPlop ; } void setPlop(int value) { mPlop = value; } int baz() { return mBaz ; } void setBaz(int value) { mBaz = value; } + QString blub() const { return mBlub; } + void setBlub(const QString &value) { mBlub = value; } + QString mBlub; + const QString mConst; private: int mBar; int mPlop; int mBaz; }; public: - PrivatePropertyTest() : mFoo(0), d (new MyDPointer) {} + PrivatePropertyTest(QObject *parent = 0) : QObject(parent), mFoo(0), d (new MyDPointer) {} int foo() { return mFoo ; } void setFoo(int value) { mFoo = value; } MyDPointer *d_func() {return d;} +signals: + void blub4Changed(); + void blub5Changed(const QString &newBlub); private: int mFoo; MyDPointer *d; @@ -1229,14 +1258,15 @@ void tst_Moc::warnOnPropertyWithoutREAD() #endif #if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; - proc.start("moc", QStringList(srcify("warn-on-property-without-read.h"))); + const QString header = m_sourceDirectory + QStringLiteral("/warn-on-property-without-read.h"); + proc.start("moc", QStringList(header)); QVERIFY(proc.waitForFinished()); QCOMPARE(proc.exitCode(), 0); QByteArray mocOut = proc.readAllStandardOutput(); QVERIFY(!mocOut.isEmpty()); QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError()); - QCOMPARE(mocWarning, QString(SRCDIR) + - QString("/warn-on-property-without-read.h:46: Warning: Property declaration foo has no READ accessor function. The property will be invalid.\n")); + QCOMPARE(mocWarning, header + + QString(":46: Warning: Property declaration foo has no READ accessor function or associated MEMBER variable. The property will be invalid.\n")); #else QSKIP("Only tested on linux/gcc"); #endif @@ -1339,14 +1369,15 @@ void tst_Moc::warnOnVirtualSignal() #endif #if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; - proc.start("moc", QStringList(srcify("pure-virtual-signals.h"))); + const QString header = m_sourceDirectory + QStringLiteral("/pure-virtual-signals.h"); + proc.start("moc", QStringList(header)); QVERIFY(proc.waitForFinished()); QCOMPARE(proc.exitCode(), 0); QByteArray mocOut = proc.readAllStandardOutput(); QVERIFY(!mocOut.isEmpty()); QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError()); - QCOMPARE(mocWarning, QString(SRCDIR) + QString("/pure-virtual-signals.h:48: Warning: Signals cannot be declared virtual\n") + - QString(SRCDIR) + QString("/pure-virtual-signals.h:50: Warning: Signals cannot be declared virtual\n")); + QCOMPARE(mocWarning, header + QString(":48: Warning: Signals cannot be declared virtual\n") + + header + QString(":50: Warning: Signals cannot be declared virtual\n")); #else QSKIP("Only tested on linux/gcc"); #endif @@ -1451,15 +1482,16 @@ void tst_Moc::notifyError() #endif #if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; - proc.start("moc", QStringList(srcify("error-on-wrong-notify.h"))); + const QString header = m_sourceDirectory + QStringLiteral("/error-on-wrong-notify.h"); + proc.start("moc", QStringList(header)); QVERIFY(proc.waitForFinished()); QCOMPARE(proc.exitCode(), 1); QCOMPARE(proc.exitStatus(), QProcess::NormalExit); QByteArray mocOut = proc.readAllStandardOutput(); QVERIFY(mocOut.isEmpty()); QString mocError = QString::fromLocal8Bit(proc.readAllStandardError()); - QCOMPARE(mocError, QString(SRCDIR) + - QString("/error-on-wrong-notify.h:52: Error: NOTIFY signal 'fooChanged' of property 'foo' does not exist in class ClassWithWrongNOTIFY.\n")); + QCOMPARE(mocError, header + + QString(":52: Error: NOTIFY signal 'fooChanged' of property 'foo' does not exist in class ClassWithWrongNOTIFY.\n")); #else QSKIP("Only tested on linux/gcc"); #endif @@ -1640,7 +1672,7 @@ void tst_Moc::warnings_data() << QStringList() << 0 << QString("IGNORE_ALL_STDOUT") - << QString("standard input:1: Warning: Property declaration x has no READ accessor function. The property will be invalid."); + << QString("standard input:1: Warning: Property declaration x has no READ accessor function or associated MEMBER variable. The property will be invalid."); // Passing "-nn" should NOT suppress the warning QTest::newRow("Invalid property warning with -nn") @@ -1648,7 +1680,7 @@ void tst_Moc::warnings_data() << (QStringList() << "-nn") << 0 << QString("IGNORE_ALL_STDOUT") - << QString("standard input:1: Warning: Property declaration x has no READ accessor function. The property will be invalid."); + << QString("standard input:1: Warning: Property declaration x has no READ accessor function or associated MEMBER variable. The property will be invalid."); // Passing "-nw" should suppress the warning QTest::newRow("Invalid property warning with -nw") @@ -1782,6 +1814,103 @@ void tst_Moc::returnRefs() // they used to cause miscompilation of the moc generated file. } +void tst_Moc::memberProperties_data() +{ + QTest::addColumn<int>("object"); + QTest::addColumn<QString>("property"); + QTest::addColumn<QString>("signal"); + QTest::addColumn<QString>("writeValue"); + QTest::addColumn<bool>("expectedWriteResult"); + QTest::addColumn<QString>("expectedReadResult"); + + pPPTest = new PrivatePropertyTest( this ); + + QTest::newRow("MEMBER property") + << 0 << "member1" << "" << "abc" << true << "abc"; + QTest::newRow("MEMBER property with READ function") + << 0 << "member2" << "" << "def" << true << "def"; + QTest::newRow("MEMBER property with WRITE function") + << 0 << "member3" << "" << "ghi" << true << "ghi"; + QTest::newRow("MEMBER property with NOTIFY") + << 0 << "member4" << "member4Changed()" << "lmn" << true << "lmn"; + QTest::newRow("MEMBER property with NOTIFY(value)") + << 0 << "member5" << "member5Changed(const QString&)" << "opq" << true << "opq"; + QTest::newRow("MEMBER property with CONSTANT") + << 0 << "member6" << "" << "test" << false << "const"; + QTest::newRow("private MEMBER property") + << 1 << "blub" << "" << "abc" << true << "abc"; + QTest::newRow("private MEMBER property with READ function") + << 1 << "blub2" << "" << "def" << true << "def"; + QTest::newRow("private MEMBER property with WRITE function") + << 1 << "blub3" << "" << "ghi" << true << "ghi"; + QTest::newRow("private MEMBER property with NOTIFY") + << 1 << "blub4" << "blub4Changed()" << "jkl" << true << "jkl"; + QTest::newRow("private MEMBER property with NOTIFY(value)") + << 1 << "blub5" << "blub5Changed(const QString&)" << "mno" << true << "mno"; + QTest::newRow("private MEMBER property with CONSTANT") + << 1 << "blub6" << "" << "test" << false << "const"; +} + +void tst_Moc::memberProperties() +{ + QFETCH(int, object); + QFETCH(QString, property); + QFETCH(QString, signal); + QFETCH(QString, writeValue); + QFETCH(bool, expectedWriteResult); + QFETCH(QString, expectedReadResult); + + QObject *pObj = (object == 0) ? this : static_cast<QObject*>(pPPTest); + + QString sSignalDeclaration; + if (!signal.isEmpty()) + sSignalDeclaration = QString(SIGNAL(%1)).arg(signal); + else + QTest::ignoreMessage(QtWarningMsg, "QSignalSpy: Not a valid signal, use the SIGNAL macro"); + QSignalSpy notifySpy(pObj, sSignalDeclaration.toLatin1().constData()); + + int index = pObj->metaObject()->indexOfProperty(property.toLatin1().constData()); + QVERIFY(index != -1); + QMetaProperty prop = pObj->metaObject()->property(index); + + QCOMPARE(prop.write(pObj, writeValue), expectedWriteResult); + + QVariant readValue = prop.read(pObj); + QCOMPARE(readValue.toString(), expectedReadResult); + + if (!signal.isEmpty()) + { + QCOMPARE(notifySpy.count(), 1); + if (prop.notifySignal().parameterNames().size() > 0) { + QList<QVariant> arguments = notifySpy.takeFirst(); + QCOMPARE(arguments.size(), 1); + QCOMPARE(arguments.at(0).toString(), expectedReadResult); + } + + notifySpy.clear(); + // a second write with the same value should not cause the signal to be emitted again + QCOMPARE(prop.write(pObj, writeValue), expectedWriteResult); + QCOMPARE(notifySpy.count(), 0); + } +} + +//this used to fail to compile +class ClassWithOneMember : public QObject { + Q_PROPERTY(int member MEMBER member) + Q_OBJECT +public: + int member; +}; + +void tst_Moc::memberProperties2() +{ + ClassWithOneMember o; + o.member = 442; + QCOMPARE(o.property("member").toInt(), 442); + QVERIFY(o.setProperty("member", 6666)); + QCOMPARE(o.member, 6666); +} + class SignalConnectionTester : public QObject { Q_OBJECT @@ -2389,6 +2518,7 @@ struct CustomObject8 {}; struct CustomObject9 {}; struct CustomObject10 {}; struct CustomObject11 {}; +struct CustomObject12 {}; Q_DECLARE_METATYPE(CustomObject3) Q_DECLARE_METATYPE(CustomObject4) @@ -2399,6 +2529,7 @@ Q_DECLARE_METATYPE(CustomObject8) Q_DECLARE_METATYPE(CustomObject9) Q_DECLARE_METATYPE(CustomObject10) Q_DECLARE_METATYPE(CustomObject11) +Q_DECLARE_METATYPE(CustomObject12) class AutoRegistrationObject : public QObject { @@ -2521,6 +2652,9 @@ public slots: void ref2(QList<int>&) {} void ref3(CustomQObject2&) {} void ref4(QSharedPointer<CustomQObject2>&) {} + +signals: + void someSignal(CustomObject12); }; void tst_Moc::autoPropertyMetaTypeRegistration() @@ -2584,6 +2718,16 @@ void tst_Moc::autoMethodArgumentMetaTypeRegistration() int i = metaObject->methodOffset(); // Start after QObject built-in slots; + while (i < metaObject->methodCount()) { + // Skip over signals so we start at the first slot. + const QMetaMethod method = metaObject->method(i); + if (method.methodType() == QMetaMethod::Signal) + ++i; + else + break; + + } + #define TYPE_LOOP(TYPE) \ { \ const QMetaMethod method = metaObject->method(i); \ @@ -2710,6 +2854,26 @@ void tst_Moc::autoMethodArgumentMetaTypeRegistration() } +void tst_Moc::autoSignalSpyMetaTypeRegistration() +{ + AutoRegistrationObject aro; + + QVector<int> methodArgMetaTypeIds; + + const QMetaObject *metaObject = aro.metaObject(); + + int i = metaObject->indexOfSignal(QMetaObject::normalizedSignature("someSignal(CustomObject12)")); + + QVERIFY(i > 0); + + QCOMPARE(QMetaType::type("CustomObject12"), (int)QMetaType::UnknownType); + + QSignalSpy spy(&aro, SIGNAL(someSignal(CustomObject12))); + + QVERIFY(QMetaType::type("CustomObject12") != QMetaType::UnknownType); + QCOMPARE(QMetaType::type("CustomObject12"), qMetaTypeId<CustomObject12>()); +} + void tst_Moc::parseDefines() { const QMetaObject *mo = &PD_NAMESPACE::PD_CLASSNAME::staticMetaObject; @@ -2792,7 +2956,7 @@ void tst_Moc::preprocessorOnly() #endif #if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; - proc.start("moc", QStringList() << "-E" << srcify("/pp-dollar-signs.h")); + proc.start("moc", QStringList() << "-E" << m_sourceDirectory + QStringLiteral("/pp-dollar-signs.h")); QVERIFY(proc.waitForFinished()); QCOMPARE(proc.exitCode(), 0); QByteArray mocOut = proc.readAllStandardOutput(); @@ -2813,7 +2977,7 @@ void tst_Moc::unterminatedFunctionMacro() #endif #if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; - proc.start("moc", QStringList() << "-E" << srcify("/unterminated-function-macro.h")); + proc.start("moc", QStringList() << "-E" << m_sourceDirectory + QStringLiteral("/unterminated-function-macro.h")); QVERIFY(proc.waitForFinished()); QCOMPARE(proc.exitCode(), 1); QCOMPARE(proc.readAllStandardOutput(), QByteArray()); diff --git a/tests/auto/tools/qmake/tst_qmake.cpp b/tests/auto/tools/qmake/tst_qmake.cpp index 186ecd77a4..0935b1bca4 100644 --- a/tests/auto/tools/qmake/tst_qmake.cpp +++ b/tests/auto/tools/qmake/tst_qmake.cpp @@ -85,8 +85,7 @@ private slots: void one_space(); void findMocs(); void findDeps(); -#ifndef Q_OS_WIN - // Test requires make +#if defined(Q_OS_MAC) void bundle_spaces(); #endif void includefunction(); @@ -456,7 +455,7 @@ struct TempFile } }; -#ifndef Q_OS_WIN +#if defined(Q_OS_MAC) void tst_qmake::bundle_spaces() { QString workDir = base_path + "/testdata/bundle-spaces"; @@ -465,7 +464,7 @@ void tst_qmake::bundle_spaces() // Bundles and since this might be the wrong output we rely on dry-running // make (-n). - test_compiler.setArguments("-n", "-spec macx-g++"); + test_compiler.setArguments("-n", "-spec macx-clang"); QVERIFY( test_compiler.qmake(workDir, "bundle-spaces") ); @@ -486,7 +485,7 @@ void tst_qmake::bundle_spaces() QVERIFY( !non_existing_file.exists() ); QVERIFY( test_compiler.removeMakefile(workDir) ); } -#endif // Q_OS_WIN +#endif // defined(Q_OS_MAC) void tst_qmake::includefunction() { diff --git a/tests/auto/widgets/dialogs/dialogs.pro b/tests/auto/widgets/dialogs/dialogs.pro index 034f37c6e0..e767c9767e 100644 --- a/tests/auto/widgets/dialogs/dialogs.pro +++ b/tests/auto/widgets/dialogs/dialogs.pro @@ -20,3 +20,4 @@ wince*:SUBDIRS -= qabstractprintdialog qsidebar \ mac:qinputdialog.CONFIG += no_check_target # QTBUG-25496 +win32-g++*: SUBDIRS -= qfilesystemmodel # QTBUG-29403 diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/qfilesystemmodel.pro b/tests/auto/widgets/dialogs/qfilesystemmodel/qfilesystemmodel.pro index 5606033240..78639e87a5 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/qfilesystemmodel.pro +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/qfilesystemmodel.pro @@ -1,6 +1,6 @@ CONFIG += testcase -CONFIG += parallel_test -win32:testcase.timeout = 900 # this testcase can be slow on Windows +# This testcase can be slow on Windows and may interfere with other file system tests. +win32:testcase.timeout = 900 QT += widgets widgets-private QT += core-private gui testlib diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index db80aa1b22..e36eaa5af2 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -48,6 +48,7 @@ #include <QFileIconProvider> #include <QTreeView> #include <QHeaderView> +#include <QStandardPaths> #include <QTime> #include <QStyle> #include <QtGlobal> @@ -109,6 +110,7 @@ private slots: void setData_data(); void setData(); + void sortPersistentIndex(); void sort_data(); void sort(); @@ -207,27 +209,30 @@ void tst_QFileSystemModel::rootPath() QCOMPARE(rootChanged.count(), 0); QString oldRootPath = model->rootPath(); - root = model->setRootPath(QDir::homePath()); + const QStringList documentPaths = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); + QVERIFY(!documentPaths.isEmpty()); + const QString documentPath = documentPaths.front(); + root = model->setRootPath(documentPath); QTRY_VERIFY(model->rowCount(root) >= 0); - QCOMPARE(model->rootPath(), QString(QDir::homePath())); + QCOMPARE(model->rootPath(), QString(documentPath)); QCOMPARE(rootChanged.count(), oldRootPath == model->rootPath() ? 0 : 1); - QCOMPARE(model->rootDirectory().absolutePath(), QDir::homePath()); + QCOMPARE(model->rootDirectory().absolutePath(), documentPath); model->setRootPath(QDir::rootPath()); int oldCount = rootChanged.count(); oldRootPath = model->rootPath(); - root = model->setRootPath(QDir::homePath() + QLatin1String("/.")); + root = model->setRootPath(documentPath + QLatin1String("/.")); QTRY_VERIFY(model->rowCount(root) >= 0); - QCOMPARE(model->rootPath(), QDir::homePath()); + QCOMPARE(model->rootPath(), documentPath); QCOMPARE(rootChanged.count(), oldRootPath == model->rootPath() ? oldCount : oldCount + 1); - QCOMPARE(model->rootDirectory().absolutePath(), QDir::homePath()); + QCOMPARE(model->rootDirectory().absolutePath(), documentPath); - QDir newdir = QDir::home(); + QDir newdir = documentPath; if (newdir.cdUp()) { oldCount = rootChanged.count(); oldRootPath = model->rootPath(); - root = model->setRootPath(QDir::homePath() + QLatin1String("/..")); + root = model->setRootPath(documentPath + QLatin1String("/..")); QTRY_VERIFY(model->rowCount(root) >= 0); QCOMPARE(model->rootPath(), newdir.path()); QCOMPARE(rootChanged.count(), oldCount + 1); @@ -310,9 +315,9 @@ void tst_QFileSystemModel::naturalCompare() void tst_QFileSystemModel::readOnly() { QCOMPARE(model->isReadOnly(), true); - QTemporaryFile file; + QTemporaryFile file(flatDirTestPath + QStringLiteral("/XXXXXX.dat")); file.open(); - QModelIndex root = model->setRootPath(QDir::tempPath()); + QModelIndex root = model->setRootPath(flatDirTestPath); QTRY_VERIFY(model->rowCount(root) > 0); QVERIFY(!(model->flags(model->index(file.fileName())) & Qt::ItemIsEditable)); @@ -358,7 +363,10 @@ void tst_QFileSystemModel::iconProvider() delete p; QFileSystemModel *myModel = new QFileSystemModel(); - myModel->setRootPath(QDir::homePath()); + const QStringList documentPaths = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); + QVERIFY(!documentPaths.isEmpty()); + const QString documentPath = documentPaths.front(); + myModel->setRootPath(documentPath); //Let's wait to populate the model QTest::qWait(250); //We change the provider, icons must me updated @@ -791,6 +799,19 @@ void tst_QFileSystemModel::setData() QTRY_COMPARE(model->rowCount(root), files.count()); } +void tst_QFileSystemModel::sortPersistentIndex() +{ + QTemporaryFile file(flatDirTestPath + QStringLiteral("/XXXXXX.dat")); + file.open(); + QModelIndex root = model->setRootPath(flatDirTestPath); + QTRY_VERIFY(model->rowCount(root) > 0); + + QPersistentModelIndex idx = model->index(0, 1, root); + model->sort(0, Qt::AscendingOrder); + model->sort(0, Qt::DescendingOrder); + QVERIFY(idx.column() != 0); +} + class MyFriendFileSystemModel : public QFileSystemModel { friend class tst_QFileSystemModel; @@ -806,18 +827,6 @@ void tst_QFileSystemModel::sort_data() void tst_QFileSystemModel::sort() { - QTemporaryFile file; - file.open(); - QModelIndex root = model->setRootPath(QDir::tempPath()); - QTRY_VERIFY(model->rowCount(root) > 0); - - QPersistentModelIndex idx = model->index(0, 1, root); - model->sort(0, Qt::AscendingOrder); - model->sort(0, Qt::DescendingOrder); - QVERIFY(idx.column() != 0); - - model->setRootPath(QDir::homePath()); - QFETCH(bool, fileDialogMode); MyFriendFileSystemModel *myModel = new MyFriendFileSystemModel(); diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp index b14e68951b..56cf27155d 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp @@ -424,6 +424,7 @@ private slots: void activate(); void setActivePanelOnInactiveScene(); void activationOnShowHide(); + void deactivateInactivePanel(); void moveWhileDeleting(); void ensureDirtySceneTransform(); void focusScope(); @@ -2204,7 +2205,6 @@ void tst_QGraphicsItem::sceneMatrix() void tst_QGraphicsItem::setMatrix() { QGraphicsScene scene; - qRegisterMetaType<QList<QRectF> >("QList<QRectF>"); QSignalSpy spy(&scene, SIGNAL(changed(QList<QRectF>))); QRectF unrotatedRect(-12, -34, 56, 78); QGraphicsRectItem item(unrotatedRect, 0); @@ -9030,6 +9030,40 @@ public: } }; +void tst_QGraphicsItem::deactivateInactivePanel() +{ + QGraphicsScene scene; + QGraphicsItem *panel1 = scene.addRect(QRectF(0, 0, 10, 10)); + panel1->setFlag(QGraphicsItem::ItemIsPanel); + + QGraphicsItem *panel2 = scene.addRect(QRectF(0, 0, 10, 10)); + panel2->setFlag(QGraphicsItem::ItemIsPanel); + + QEvent event(QEvent::WindowActivate); + qApp->sendEvent(&scene, &event); + + panel1->setActive(true); + QVERIFY(scene.isActive()); + QVERIFY(panel1->isActive()); + QVERIFY(!panel2->isActive()); + QCOMPARE(scene.activePanel(), panel1); + + panel2->setActive(true); + QVERIFY(panel2->isActive()); + QVERIFY(!panel1->isActive()); + QCOMPARE(scene.activePanel(), panel2); + + panel2->setActive(false); + QVERIFY(panel1->isActive()); + QVERIFY(!panel2->isActive()); + QCOMPARE(scene.activePanel(), panel1); + + panel2->setActive(false); + QVERIFY(panel1->isActive()); + QVERIFY(!panel2->isActive()); + QCOMPARE(scene.activePanel(), panel1); +} + void tst_QGraphicsItem::moveWhileDeleting() { QGraphicsScene scene; @@ -10333,23 +10367,24 @@ void tst_QGraphicsItem::modality_clickFocus() EventSpy2 rect1Spy(&scene, rect1); EventSpy2 rect2Spy(&scene, rect2); - // activate rect1, it should not get focus + // activate rect1, it should get focus rect1->setActive(true); - QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0); + QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1); - // focus stays unset when rect2 becomes modal + // focus stays when rect2 becomes modal rect2->setPanelModality(QGraphicsItem::SceneModal); - QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0); - QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0); + QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1); + QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 1); QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0); QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0); QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0); // clicking on rect1 should not set it's focus item + rect1->clearFocus(); sendMouseClick(&scene, QPointF(-25, -25)); QCOMPARE(rect1->focusItem(), (QGraphicsItem *) 0); - QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0); - QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0); + QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 1); + QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 1); QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0); QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0); @@ -10357,33 +10392,34 @@ void tst_QGraphicsItem::modality_clickFocus() rect2->setActive(true); sendMouseClick(&scene, QPointF(75, 75)); QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect2); - QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0); - QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0); + QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 1); + QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 1); QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1); QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0); // clicking on rect1 does *not* give it focus rect1->setActive(true); + rect1->clearFocus(); sendMouseClick(&scene, QPointF(-25, -25)); QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0); - QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0); - QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0); + QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 2); + QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 2); QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1); QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1); // focus doesn't change when leaving modality either rect2->setPanelModality(QGraphicsItem::NonModal); QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0); - QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0); - QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0); + QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 2); + QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 2); QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1); QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1); // click on rect1, it should get focus now sendMouseClick(&scene, QPointF(-25, -25)); QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1); - QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 1); - QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0); + QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 3); + QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 2); QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1); QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1); } diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp index 7a5f7319bc..b80c00e88e 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp @@ -266,6 +266,7 @@ private slots: void siblingIndexAlwaysValid(); void removeFullyTransparentItem(); void zeroScale(); + void focusItemChangedSignal(); // task specific tests below me void task139710_bspTreeCrash(); @@ -3883,11 +3884,11 @@ void tst_QGraphicsScene::initialFocus_data() QTest::addColumn<bool>("shouldHaveFocus"); QTest::newRow("inactive scene, normal item") << false << false << false << false; - QTest::newRow("inactive scene, panel item") << false << false << true << false; + QTest::newRow("inactive scene, panel item") << false << false << true << true; QTest::newRow("inactive scene, normal item, explicit focus") << false << true << false << true; QTest::newRow("inactive scene, panel, explicit focus") << false << true << true << true; QTest::newRow("active scene, normal item") << true << false << false << false; - QTest::newRow("active scene, panel item") << true << false << true << false; + QTest::newRow("active scene, panel item") << true << false << true << true; QTest::newRow("active scene, normal item, explicit focus") << true << true << false << true; QTest::newRow("active scene, panel, explicit focus") << true << true << true << true; } @@ -4561,6 +4562,119 @@ void tst_QGraphicsScene::zeroScale() QTRY_COMPARE(cl.changes.count(), 2); } +void tst_QGraphicsScene::focusItemChangedSignal() +{ + qRegisterMetaType<QGraphicsItem *>("QGraphicsItem *"); + qRegisterMetaType<Qt::FocusReason>("Qt::FocusReason"); + + QGraphicsScene scene; + QSignalSpy spy(&scene, SIGNAL(focusItemChanged(QGraphicsItem *, QGraphicsItem *, Qt::FocusReason))); + QVERIFY(spy.isValid()); + QCOMPARE(spy.count(), 0); + scene.setFocus(); + QCOMPARE(spy.count(), 0); + QEvent activateEvent(QEvent::WindowActivate); + qApp->sendEvent(&scene, &activateEvent); + QCOMPARE(spy.count(), 0); + + QGraphicsRectItem *topLevelItem1 = new QGraphicsRectItem; + topLevelItem1->setFlag(QGraphicsItem::ItemIsFocusable); + scene.addItem(topLevelItem1); + QCOMPARE(spy.count(), 0); + QVERIFY(!topLevelItem1->hasFocus()); + + QGraphicsRectItem *topLevelItem2 = new QGraphicsRectItem; + topLevelItem2->setFlag(QGraphicsItem::ItemIsFocusable); + topLevelItem2->setFocus(); + QVERIFY(!topLevelItem2->hasFocus()); + scene.addItem(topLevelItem2); + QCOMPARE(spy.count(), 1); + QList<QVariant> arguments = spy.takeFirst(); + QCOMPARE(arguments.size(), 3); + QCOMPARE(qVariantValue<QGraphicsItem *>(arguments.at(0)), (QGraphicsItem *)topLevelItem2); + QCOMPARE(qVariantValue<QGraphicsItem *>(arguments.at(1)), (QGraphicsItem *)0); + QCOMPARE(qVariantValue<Qt::FocusReason>(arguments.at(2)), Qt::OtherFocusReason); + QVERIFY(topLevelItem2->hasFocus()); + + scene.clearFocus(); + QCOMPARE(spy.count(), 1); + arguments = spy.takeFirst(); + QCOMPARE(arguments.size(), 3); + QCOMPARE(qVariantValue<QGraphicsItem *>(arguments.at(0)), (QGraphicsItem *)0); + QCOMPARE(qVariantValue<QGraphicsItem *>(arguments.at(1)), (QGraphicsItem *)topLevelItem2); + QCOMPARE(qVariantValue<Qt::FocusReason>(arguments.at(2)), Qt::OtherFocusReason); + + scene.setFocus(Qt::MenuBarFocusReason); + QCOMPARE(spy.count(), 1); + arguments = spy.takeFirst(); + QCOMPARE(arguments.size(), 3); + QCOMPARE(qVariantValue<QGraphicsItem *>(arguments.at(0)), (QGraphicsItem *)topLevelItem2); + QCOMPARE(qVariantValue<QGraphicsItem *>(arguments.at(1)), (QGraphicsItem *)0); + QCOMPARE(qVariantValue<Qt::FocusReason>(arguments.at(2)), Qt::MenuBarFocusReason); + + for (int i = 0; i < 3; ++i) { + topLevelItem1->setFocus(Qt::TabFocusReason); + arguments = spy.takeFirst(); + QCOMPARE(arguments.size(), 3); + QCOMPARE(qVariantValue<QGraphicsItem *>(arguments.at(0)), (QGraphicsItem *)topLevelItem1); + QCOMPARE(qVariantValue<QGraphicsItem *>(arguments.at(1)), (QGraphicsItem *)topLevelItem2); + QCOMPARE(qVariantValue<Qt::FocusReason>(arguments.at(2)), Qt::TabFocusReason); + + topLevelItem2->setFocus(Qt::TabFocusReason); + arguments = spy.takeFirst(); + QCOMPARE(arguments.size(), 3); + QCOMPARE(qVariantValue<QGraphicsItem *>(arguments.at(0)), (QGraphicsItem *)topLevelItem2); + QCOMPARE(qVariantValue<QGraphicsItem *>(arguments.at(1)), (QGraphicsItem *)topLevelItem1); + QCOMPARE(qVariantValue<Qt::FocusReason>(arguments.at(2)), Qt::TabFocusReason); + } + + // The following two are unexpected, but fixing this (i.e., losing and gaining focus + // when the scene activation changes) breaks quite a few tests so leave this fix + // for some future release. See QTBUG-28346. + QEvent deactivateEvent(QEvent::WindowDeactivate); + qApp->sendEvent(&scene, &deactivateEvent); + QEXPECT_FAIL("", "QTBUG-28346", Continue); + QCOMPARE(spy.count(), 1); + qApp->sendEvent(&scene, &activateEvent); + QEXPECT_FAIL("", "QTBUG-28346", Continue); + QCOMPARE(spy.count(), 1); + + QGraphicsRectItem *panel1 = new QGraphicsRectItem; + panel1->setFlags(QGraphicsItem::ItemIsPanel | QGraphicsItem::ItemIsFocusable); + panel1->setFocus(); + scene.addItem(panel1); + QCOMPARE(spy.count(), 1); + arguments = spy.takeFirst(); + QCOMPARE(arguments.size(), 3); + QCOMPARE(qVariantValue<QGraphicsItem *>(arguments.at(0)), (QGraphicsItem *)panel1); + QCOMPARE(qVariantValue<QGraphicsItem *>(arguments.at(1)), (QGraphicsItem *)topLevelItem2); + QCOMPARE(qVariantValue<Qt::FocusReason>(arguments.at(2)), Qt::ActiveWindowFocusReason); + + QGraphicsRectItem *panel2 = new QGraphicsRectItem; + panel2->setFlags(QGraphicsItem::ItemIsPanel | QGraphicsItem::ItemIsFocusable); + scene.addItem(panel2); + QCOMPARE(spy.count(), 0); + + for (int i = 0; i < 3; ++i) { + scene.setActivePanel(panel2); + QCOMPARE(spy.count(), 1); + arguments = spy.takeFirst(); + QCOMPARE(arguments.size(), 3); + QCOMPARE(qVariantValue<QGraphicsItem *>(arguments.at(0)), (QGraphicsItem *)panel2); + QCOMPARE(qVariantValue<QGraphicsItem *>(arguments.at(1)), (QGraphicsItem *)panel1); + QCOMPARE(qVariantValue<Qt::FocusReason>(arguments.at(2)), Qt::ActiveWindowFocusReason); + + scene.setActivePanel(panel1); + QCOMPARE(spy.count(), 1); + arguments = spy.takeFirst(); + QCOMPARE(arguments.size(), 3); + QCOMPARE(qVariantValue<QGraphicsItem *>(arguments.at(0)), (QGraphicsItem *)panel1); + QCOMPARE(qVariantValue<QGraphicsItem *>(arguments.at(1)), (QGraphicsItem *)panel2); + QCOMPARE(qVariantValue<Qt::FocusReason>(arguments.at(2)), Qt::ActiveWindowFocusReason); + } + +} + void tst_QGraphicsScene::taskQTBUG_15977_renderWithDeviceCoordinateCache() { QGraphicsScene scene; diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp index 69665572f7..4cfdfccd63 100644 --- a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp @@ -172,12 +172,12 @@ private slots: void initialShow2(); void itemChangeEvents(); void itemSendGeometryPosChangesDeactivated(); - void fontPropagatesResolveToChildren(); void fontPropagatesResolveToGrandChildren(); void fontPropagatesResolveInParentChange(); void fontPropagatesResolveViaNonWidget(); void fontPropagatesResolveFromScene(); + void tabFocus(); // Task fixes void task236127_bspTreeIndexFails(); @@ -3302,6 +3302,103 @@ void tst_QGraphicsWidget::itemSendGeometryPosChangesDeactivated() QCOMPARE(item->geometry(), QRectF(10, 10, 60, 60)); } +class TabFocusWidget : public QGraphicsWidget +{ + Q_OBJECT +public: + TabFocusWidget(const QString &name, QGraphicsItem *parent = 0) + : QGraphicsWidget(parent) + { setFocusPolicy(Qt::TabFocus); setData(0, name); } +}; + +void verifyTabFocus(QGraphicsScene *scene, const QList<QGraphicsWidget *> &chain, bool wrapsAround) +{ + QKeyEvent tabEvent(QEvent::KeyPress, Qt::Key_Tab, 0); + QKeyEvent backtabEvent(QEvent::KeyPress, Qt::Key_Backtab, 0); + + for (int i = 0; i < chain.size(); ++i) + chain.at(i)->clearFocus(); + + int n = chain.size() * (wrapsAround ? 3 : 1); + for (int i = 0; i < n; ++i) + { + qApp->sendEvent(scene, &tabEvent); + QVERIFY(chain.at(i % chain.size())->hasFocus()); + QCOMPARE(scene->focusItem(), chain.at(i % chain.size())); + } + for (int i = n - 2; i >= 0; --i) + { + qApp->sendEvent(scene, &backtabEvent); + QVERIFY(chain.at(i % chain.size())->hasFocus()); + QCOMPARE(scene->focusItem(), chain.at(i % chain.size())); + } +} + +void tst_QGraphicsWidget::tabFocus() +{ + QGraphicsScene scene; + scene.setFocus(); + + QEvent activate(QEvent::WindowActivate); + qApp->sendEvent(&scene, &activate); + + TabFocusWidget *widget = new TabFocusWidget("1"); + scene.addItem(widget); + verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget, false); + + TabFocusWidget *widget2 = new TabFocusWidget("2"); + scene.addItem(widget2); + scene.setFocusItem(0); + verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget << widget2, false); + + TabFocusWidget *widget3 = new TabFocusWidget("3"); + widget3->setFlag(QGraphicsItem::ItemIsPanel); + scene.addItem(widget3); + QCOMPARE(scene.activePanel(), (QGraphicsItem *)widget3); + scene.setActivePanel(0); + scene.setFocusItem(0); + verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget << widget2, false); + + scene.setActivePanel(widget3); + QCOMPARE(scene.focusItem(), (QGraphicsItem *)widget3); + verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3, true); + + TabFocusWidget *widget4 = new TabFocusWidget("4"); + widget4->setParentItem(widget3); + QVERIFY(widget3->hasFocus()); + widget3->clearFocus(); + QVERIFY(!widget3->focusItem()); + QCOMPARE(scene.activePanel(), (QGraphicsItem *)widget3); + verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4, true); + + QGraphicsWidget *widget5 = new QGraphicsWidget; widget5->setData(0, QLatin1String("5")); + widget5->setParentItem(widget3); + verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4, true); + + widget5->setFocusPolicy(Qt::TabFocus); + verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4 << widget5, true); + + TabFocusWidget *widget6 = new TabFocusWidget("6"); + widget6->setParentItem(widget4); + verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4 << widget6 << widget5, true); + + TabFocusWidget *widget7 = new TabFocusWidget("7", widget6); + verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4 << widget6 << widget7 << widget5, true); + + TabFocusWidget *widget8 = new TabFocusWidget("8", widget6); + verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4 << widget6 << widget7 << widget8 << widget5, true); + widget6->setFlag(QGraphicsItem::ItemIsPanel); + widget6->setActive(true); + verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget6 << widget7 << widget8, true); + widget3->setActive(true); + verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4 << widget5, true); + widget6->setFlag(QGraphicsItem::ItemIsPanel, false); + verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4 << widget6 << widget7 << widget8 << widget5, true); + scene.removeItem(widget6); + verifyTabFocus(&scene, QList<QGraphicsWidget *>() << widget3 << widget4 << widget5, true); + delete widget6; +} + void tst_QGraphicsWidget::QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems() { QGraphicsScene scene; diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp index 2d95c9d3a4..f0731eb3a6 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp @@ -235,6 +235,8 @@ private slots: void testDelegateDestroyEditor(); void testClickedSignal(); void testChangeEditorState(); + void deselectInSingleSelection(); + void testNoActivateOnDisabledItem(); }; class MyAbstractItemDelegate : public QAbstractItemDelegate @@ -1599,5 +1601,70 @@ void tst_QAbstractItemView::testChangeEditorState() // No segfault - the test passes. } +void tst_QAbstractItemView::deselectInSingleSelection() +{ + QTableView view; + QStandardItemModel s; + s.setRowCount(10); + s.setColumnCount(10); + view.setModel(&s); + view.show(); + view.setSelectionMode(QAbstractItemView::SingleSelection); + view.setEditTriggers(QAbstractItemView::NoEditTriggers); + QApplication::setActiveWindow(&view); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + // mouse + QModelIndex index22 = s.index(2, 2); + QRect rect22 = view.visualRect(index22); + QPoint clickpos = rect22.center(); + QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, clickpos); + QCOMPARE(view.currentIndex(), index22); + QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, clickpos); + QCOMPARE(view.currentIndex(), index22); + QCOMPARE(view.selectionModel()->selectedIndexes().count(), 0); + + // second click with modifier however does select + QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, clickpos); + QCOMPARE(view.currentIndex(), index22); + QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + + // keyboard + QTest::keyClick(&view, Qt::Key_Space, Qt::NoModifier); + QCOMPARE(view.currentIndex(), index22); + QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QTest::keyClick(&view, Qt::Key_Space, Qt::ControlModifier); + QCOMPARE(view.currentIndex(), index22); + QCOMPARE(view.selectionModel()->selectedIndexes().count(), 0); + + // second keypress with modifier however does select + QTest::keyClick(&view, Qt::Key_Space, Qt::ControlModifier); + QCOMPARE(view.currentIndex(), index22); + QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); +} + +void tst_QAbstractItemView::testNoActivateOnDisabledItem() +{ + QTreeView treeView; + QStandardItemModel model(1, 1); + QStandardItem *item = new QStandardItem("item"); + model.setItem(0, 0, item); + item->setFlags(Qt::NoItemFlags); + treeView.setModel(&model); + treeView.show(); + + QApplication::setActiveWindow(&treeView); + QVERIFY(QTest::qWaitForWindowActive(&treeView)); + + QSignalSpy activatedSpy(&treeView, SIGNAL(activated(QModelIndex))); + + // Ensure clicking on a disabled item doesn't emit itemActivated. + QModelIndex itemIndex = treeView.model()->index(0, 0); + QPoint clickPos = treeView.visualRect(itemIndex).center(); + QTest::mouseClick(treeView.viewport(), Qt::LeftButton, 0, clickPos); + + QCOMPARE(activatedSpy.count(), 0); +} + QTEST_MAIN(tst_QAbstractItemView) #include "tst_qabstractitemview.moc" diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp index 0f69e951bf..d914142e13 100644 --- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp +++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp @@ -177,6 +177,7 @@ private slots: void emptyModel(); void removeRows(); void removeCols(); + void limitedExpand(); void expandAndCollapse_data(); void expandAndCollapse(); void expandAndCollapseAll(); @@ -256,6 +257,7 @@ private slots: void taskQTBUG_13567_removeLastItemRegression(); void taskQTBUG_25333_adjustViewOptionsForIndex(); void taskQTBUG_18539_emitLayoutChanged(); + void taskQTBUG_8176_emitOnExpandAll(); }; class QtTestModel: public QAbstractItemModel @@ -1414,6 +1416,45 @@ void tst_QTreeView::removeCols() QCOMPARE(view.header()->count(), model.cols); } +void tst_QTreeView::limitedExpand() +{ + { + QStandardItemModel model; + QStandardItem *parentItem = model.invisibleRootItem(); + parentItem->appendRow(new QStandardItem); + parentItem->appendRow(new QStandardItem); + parentItem->appendRow(new QStandardItem); + + QStandardItem *firstItem = model.item(0, 0); + firstItem->setFlags(firstItem->flags() | Qt::ItemNeverHasChildren); + + QTreeView view; + view.setModel(&model); + + QSignalSpy spy(&view, SIGNAL(expanded(QModelIndex))); + QVERIFY(spy.isValid()); + + view.expand(model.index(0, 0)); + QCOMPARE(spy.count(), 0); + + view.expand(model.index(1, 0)); + QCOMPARE(spy.count(), 1); + } + { + QStringListModel model(QStringList() << "one" << "two"); + QTreeView view; + view.setModel(&model); + + QSignalSpy spy(&view, SIGNAL(expanded(QModelIndex))); + QVERIFY(spy.isValid()); + + view.expand(model.index(0, 0)); + QCOMPARE(spy.count(), 0); + view.expandAll(); + QCOMPARE(spy.count(), 0); + } +} + void tst_QTreeView::expandAndCollapse_data() { QTest::addColumn<bool>("animationEnabled"); @@ -1581,13 +1622,10 @@ void tst_QTreeView::expandAndCollapseAll() for (int r = 0; r < rows; ++r) parents.push(model.index(r, 0, p)); } -// ### why is expanded() signal not emitted? -// QCOMPARE(expandedSpy.count(), count); + QCOMPARE(expandedSpy.count(), 12); // == (3+1)*(2+1) from QtTestModel model(3, 2); view.collapseAll(); - QCOMPARE(expandedSpy.count(), 0); - parents.push(QModelIndex()); count = 0; while (!parents.isEmpty()) { @@ -1599,8 +1637,7 @@ void tst_QTreeView::expandAndCollapseAll() for (int r = 0; r < rows; ++r) parents.push(model.index(r, 0, p)); } -// ### why is collapsed() signal not emitted? -// QCOMPARE(collapsedSpy.count(), count); + QCOMPARE(collapsedSpy.count(), 12); } void tst_QTreeView::expandWithNoChildren() @@ -4158,6 +4195,47 @@ void tst_QTreeView::taskQTBUG_18539_emitLayoutChanged() QCOMPARE(afterRISpy.size(), 0); } +void tst_QTreeView::taskQTBUG_8176_emitOnExpandAll() +{ + QTreeWidget tw; + QTreeWidgetItem *item = new QTreeWidgetItem(&tw, QStringList(QString("item 1"))); + QTreeWidgetItem *item2 = new QTreeWidgetItem(item, QStringList(QString("item 2"))); + new QTreeWidgetItem(item2, QStringList(QString("item 3"))); + new QTreeWidgetItem(item2, QStringList(QString("item 4"))); + QTreeWidgetItem *item5 = new QTreeWidgetItem(&tw, QStringList(QString("item 5"))); + new QTreeWidgetItem(item5, QStringList(QString("item 6"))); + QSignalSpy spy(&tw, SIGNAL(expanded(const QModelIndex&))); + + // expand all + tw.expandAll(); + QCOMPARE(spy.size(), 6); + spy.clear(); + tw.collapseAll(); + item2->setExpanded(true); + spy.clear(); + tw.expandAll(); + QCOMPARE(spy.size(), 5); + + // collapse all + QSignalSpy spy2(&tw, SIGNAL(collapsed(const QModelIndex&))); + tw.collapseAll(); + QCOMPARE(spy2.size(), 6); + tw.expandAll(); + item2->setExpanded(false); + spy2.clear(); + tw.collapseAll(); + QCOMPARE(spy2.size(), 5); + + // expand to depth + item2->setExpanded(true); + spy.clear(); + spy2.clear(); + tw.expandToDepth(0); + + QCOMPARE(spy.size(), 2); // item and item5 are expanded + QCOMPARE(spy2.size(), 1); // item2 is collapsed +} + #ifndef QT_NO_ANIMATION void tst_QTreeView::quickExpandCollapse() { diff --git a/tests/auto/widgets/kernel/kernel.pro b/tests/auto/widgets/kernel/kernel.pro index b280f44f05..20720dc928 100644 --- a/tests/auto/widgets/kernel/kernel.pro +++ b/tests/auto/widgets/kernel/kernel.pro @@ -15,6 +15,7 @@ SUBDIRS=\ qwidgetaction \ qwidgetmetatype \ qwidgetsvariant \ + qwindowcontainer \ qshortcut \ qsizepolicy diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 78fce7661e..e6b1caf694 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -5626,6 +5626,7 @@ void tst_QWidget::showHideShowX11() qApp->installNativeEventFilter(&w); w.show(); + QVERIFY(QTest::qWaitForWindowExposed(&w)); w.hide(); QEventLoop eventLoop; diff --git a/tests/auto/widgets/kernel/qwindowcontainer/.gitignore b/tests/auto/widgets/kernel/qwindowcontainer/.gitignore new file mode 100644 index 0000000000..038f477220 --- /dev/null +++ b/tests/auto/widgets/kernel/qwindowcontainer/.gitignore @@ -0,0 +1 @@ +tst_qwindowcontainer diff --git a/tests/auto/widgets/kernel/qwindowcontainer/qwindowcontainer.pro b/tests/auto/widgets/kernel/qwindowcontainer/qwindowcontainer.pro new file mode 100644 index 0000000000..4ff05eb04a --- /dev/null +++ b/tests/auto/widgets/kernel/qwindowcontainer/qwindowcontainer.pro @@ -0,0 +1,6 @@ +CONFIG += testcase +mac:CONFIG -= app_bundle +# CONFIG += parallel_test // Cannot be parallel due to the activation test +TARGET = tst_qwindowcontainer +QT += widgets testlib +SOURCES += tst_qwindowcontainer.cpp diff --git a/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp b/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp new file mode 100644 index 0000000000..440639cd49 --- /dev/null +++ b/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> + +#include <qapplication.h> +#include <qwindow.h> +#include <qwidget.h> + + + +class Window : public QWindow +{ +public: + Window() + : numberOfExposes(0) + , numberOfObscures(0) + { + } + + void exposeEvent(QExposeEvent *) { + if (isExposed()) + ++numberOfExposes; + else + ++numberOfObscures; + } + + int numberOfExposes; + int numberOfObscures; +}; + + + +class tst_QWindowContainer: public QObject +{ + Q_OBJECT +private slots: + void testShow(); + void testPositionAndSize(); + void testExposeObscure(); + void testOwnership(); + void testBehindTheScenesDeletion(); + void testUnparenting(); + void testActivation(); +}; + + + +void tst_QWindowContainer::testShow() +{ + QWidget root; + root.setGeometry(100, 100, 400, 400); + + Window *window = new Window(); + QWidget *container = QWidget::createWindowContainer(window, &root); + + container->setGeometry(50, 50, 200, 200); + + root.show(); + + QVERIFY(QTest::qWaitForWindowExposed(window)); +} + + + +void tst_QWindowContainer::testPositionAndSize() +{ + QWindow *window = new QWindow(); + window->setGeometry(300, 400, 500, 600); + + QWidget *container = QWidget::createWindowContainer(window); + container->setGeometry(50, 50, 200, 200); + + + container->show(); + QVERIFY(QTest::qWaitForWindowExposed(container)); + + QCOMPARE(window->x(), 0); + QCOMPARE(window->y(), 0); + QCOMPARE(window->width(), container->width()); + QCOMPARE(window->height(), container->height()); +} + + + +void tst_QWindowContainer::testExposeObscure() +{ + Window *window = new Window(); + + QWidget *container = QWidget::createWindowContainer(window); + container->setGeometry(50, 50, 200, 200); + + container->show(); + QVERIFY(QTest::qWaitForWindowExposed(container)); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + QVERIFY(window->numberOfExposes > 0); + + container->hide(); + + QElapsedTimer timer; + timer.start(); + while (window->numberOfObscures == 0 && timer.elapsed() < 5000) { + QTest::qWait(10); + } + + QVERIFY(window->numberOfObscures > 0); +} + + + +void tst_QWindowContainer::testOwnership() +{ + QPointer<QWindow> window(new QWindow()); + QWidget *container = QWidget::createWindowContainer(window); + + delete container; + + QCOMPARE(window.data(), (QWindow *) 0); +} + + + +void tst_QWindowContainer::testBehindTheScenesDeletion() +{ + QWindow *window = new QWindow(); + QWidget *container = QWidget::createWindowContainer(window); + + delete window; + + // The child got removed, showing not should not have any side effects, + // such as for instance, crashing... + container->show(); + QVERIFY(QTest::qWaitForWindowExposed(container)); + delete container; +} + + + +void tst_QWindowContainer::testActivation() +{ + QWidget root; + + QWindow *window = new QWindow(); + QWidget *container = QWidget::createWindowContainer(window, &root); + + container->setGeometry(100, 100, 200, 100); + root.setGeometry(100, 100, 400, 300); + + root.show(); + root.activateWindow(); + + QVERIFY(QTest::qWaitForWindowActive(root.windowHandle())); + QVERIFY(QGuiApplication::focusWindow() == root.windowHandle()); + + // Under KDE (ubuntu 12.10), we experience that doing two activateWindow in a row + // does not work. The second gets ignored by the window manager, even though the + // timestamp in the xcb connection is unique for both. + if (QGuiApplication::platformName() == "xcb") + QTest::qWait(100); + + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(QGuiApplication::focusWindow() == window); +} + + + +void tst_QWindowContainer::testUnparenting() +{ + QWindow *window = new QWindow(); + QWidget *container = QWidget::createWindowContainer(window); + container->setGeometry(100, 100, 200, 100); + + window->setParent(0); + + container->show(); + + QVERIFY(QTest::qWaitForWindowExposed(container)); + + // Window should not be made visible by container.. + QVERIFY(!window->isVisible()); +} + +QTEST_MAIN(tst_QWindowContainer) + +#include "tst_qwindowcontainer.moc" diff --git a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp index cf867194cc..a3670cccc2 100644 --- a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp +++ b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp @@ -234,7 +234,10 @@ void tst_QStyle::testProxyStyle() QVERIFY(proxyStyle->baseStyle()); qApp->setStyle(proxyStyle); - QProxyStyle doubleProxy(new QProxyStyle(QStyleFactory::create("Windows"))); + QProxyStyle* baseStyle = new QProxyStyle("Windows"); + QCOMPARE(baseStyle->baseStyle()->objectName(), style->objectName()); + + QProxyStyle doubleProxy(baseStyle); QVERIFY(testAllFunctions(&doubleProxy)); CustomProxy customStyle; @@ -775,7 +778,7 @@ void tst_QStyle::testDrawingShortcuts() class FrameTestStyle : public QProxyStyle { public: - FrameTestStyle() : QProxyStyle(QStyleFactory::create("Windows")) { } + FrameTestStyle() : QProxyStyle("Windows") { } int styleHint(StyleHint hint, const QStyleOption *opt, const QWidget *widget, QStyleHintReturn *returnData) const { if (hint == QStyle::SH_ScrollView_FrameOnlyAroundContents) return 1; diff --git a/tests/auto/widgets/util/qscroller/tst_qscroller.cpp b/tests/auto/widgets/util/qscroller/tst_qscroller.cpp index fa0db59311..39ad180d1f 100644 --- a/tests/auto/widgets/util/qscroller/tst_qscroller.cpp +++ b/tests/auto/widgets/util/qscroller/tst_qscroller.cpp @@ -391,11 +391,6 @@ void tst_QScroller::scrollTo() void tst_QScroller::scroll() { -#if defined(Q_OS_MACX) && (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6) - QSKIP("Mac OS X < 10.6 does not support QTouchEvents"); - return; -#endif - #ifndef QT_NO_GESTURES // -- good case. normal scroll tst_QScrollerWidget *sw = new tst_QScrollerWidget(); @@ -438,11 +433,6 @@ void tst_QScroller::scroll() void tst_QScroller::overshoot() { -#if defined(Q_OS_MACX) && (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6) - QSKIP("Mac OS X < 10.6 does not support QTouchEvents"); - return; -#endif - #ifndef QT_NO_GESTURES tst_QScrollerWidget *sw = new tst_QScrollerWidget(); sw->scrollArea = QRectF(0, 0, 1000, 1000); diff --git a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp index 9ecb0650c5..e7d62f8c0c 100644 --- a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp +++ b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp @@ -316,7 +316,6 @@ void tst_QDateTimeEdit::getSetCheck() tst_QDateTimeEdit::tst_QDateTimeEdit() { - qRegisterMetaType<QList<int> >("QList<int>"); } tst_QDateTimeEdit::~tst_QDateTimeEdit() @@ -759,6 +758,11 @@ void tst_QDateTimeEdit::displayFormat() void tst_QDateTimeEdit::selectAndScrollWithKeys() { +#ifdef Q_OS_MAC + QSKIP("QTBUG-23674"); + return; +#endif + qApp->setActiveWindow(testWidget); testWidget->setDate(QDate(2004, 05, 11)); testWidget->setDisplayFormat("dd/MM/yyyy"); @@ -769,9 +773,6 @@ void tst_QDateTimeEdit::selectAndScrollWithKeys() QTest::keyClick(testWidget, Qt::Key_Home); #endif QTest::keyClick(testWidget, Qt::Key_Right, Qt::ShiftModifier); -#ifdef Q_OS_MAC - QEXPECT_FAIL("", "QTBUG-23674", Abort); -#endif QCOMPARE(testWidget->lineEdit()->selectedText(), QString("1")); QTest::keyClick(testWidget, Qt::Key_Right, Qt::ShiftModifier); QCOMPARE(testWidget->lineEdit()->selectedText(), QString("11")); diff --git a/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp b/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp index c7c9980f13..59be9bd659 100644 --- a/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp +++ b/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp @@ -68,8 +68,8 @@ public slots: private slots: void standardButtons(); void testConstructor1(); - void testConstrurtor2(); - void testConstrurtor2_data(); + void testConstructor2(); + void testConstructor2_data(); void testConstructor3(); void testConstructor3_data(); void setOrientation_data(); @@ -146,7 +146,7 @@ void tst_QDialogButtonBox::layoutReuse() delete box; } -void tst_QDialogButtonBox::testConstrurtor2_data() +void tst_QDialogButtonBox::testConstructor2_data() { QTest::addColumn<int>("orientation"); @@ -154,7 +154,7 @@ void tst_QDialogButtonBox::testConstrurtor2_data() QTest::newRow("vertical") << int(Qt::Vertical); } -void tst_QDialogButtonBox::testConstrurtor2() +void tst_QDialogButtonBox::testConstructor2() { QFETCH(int, orientation); Qt::Orientation orient = Qt::Orientation(orientation); diff --git a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp index 354ccea06c..519aa61061 100644 --- a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp +++ b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp @@ -1122,7 +1122,6 @@ void tst_QMenuBar::check_menuPosition() void tst_QMenuBar::task223138_triggered() { - qRegisterMetaType<QAction *>("QAction *"); //we create a window with submenus and we check that both menubar and menus get the triggered signal QMainWindow win; QMenu *menu = win.menuBar()->addMenu("test"); diff --git a/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp b/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp index 0696aa11d2..e373e50e0a 100644 --- a/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp +++ b/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp @@ -42,6 +42,7 @@ #include <QtTest/QtTest> #include "qprogressbar.h" +#include <qlocale.h> #include <qapplication.h> #include <qstyleoption.h> #include <qdebug.h> @@ -64,6 +65,7 @@ private slots: void sizeHint(); void formatedText_data(); void formatedText(); + void localizedFormattedText(); void task245201_testChangeStyleAndDelete_data(); void task245201_testChangeStyleAndDelete(); @@ -310,6 +312,40 @@ void tst_QProgressBar::formatedText() QCOMPARE(bar.text(), text); } +void tst_QProgressBar::localizedFormattedText() // QTBUG-28751 +{ + QProgressBar bar; + const int value = 42; + bar.setValue(value); + const QString defaultExpectedNumber = QString::number(value); + const QString defaultExpectedValue = defaultExpectedNumber + QLatin1Char('%'); + QCOMPARE(bar.text(), defaultExpectedValue); + + // Temporarily switch to Egyptian, which has a different percent sign and number formatting + QLocale egypt(QLocale::Arabic, QLocale::Egypt); + bar.setLocale(egypt); + const QString egyptianExpectedNumber = egypt.toString(value); + const QString egyptianExpectedValue = egyptianExpectedNumber + egypt.percent(); + if (egyptianExpectedValue == defaultExpectedValue) + QSKIP("Egyptian locale does not work on this system."); + QCOMPARE(bar.text(), egyptianExpectedValue); + + bar.setLocale(QLocale()); + QCOMPARE(bar.text(), defaultExpectedValue); + + // Set a custom format containing only the number + bar.setFormat(QStringLiteral("%p")); + QCOMPARE(bar.text(), defaultExpectedNumber); + bar.setLocale(egypt); + QCOMPARE(bar.text(), egyptianExpectedNumber); + + // Clear the format + bar.resetFormat(); + QCOMPARE(bar.text(), egyptianExpectedValue); + bar.setLocale(QLocale()); + QCOMPARE(bar.text(), defaultExpectedValue); +} + void tst_QProgressBar::task245201_testChangeStyleAndDelete_data() { QTest::addColumn<QString>("style1_str"); diff --git a/tests/auto/xml/sax/sax.pro b/tests/auto/xml/sax/sax.pro index 13aeb21d07..d232ee90e7 100644 --- a/tests/auto/xml/sax/sax.pro +++ b/tests/auto/xml/sax/sax.pro @@ -1,6 +1,8 @@ TEMPLATE=subdirs SUBDIRS=\ - qxmlinputsource \ qxml \ + +qtHaveModule(network): SUBDIRS += \ + qxmlinputsource \ qxmlsimplereader \ diff --git a/tests/benchmarks/benchmarks.pro b/tests/benchmarks/benchmarks.pro index 5fd8ff6368..e5a6f5d7d2 100644 --- a/tests/benchmarks/benchmarks.pro +++ b/tests/benchmarks/benchmarks.pro @@ -2,11 +2,11 @@ TEMPLATE = subdirs SUBDIRS = \ corelib \ gui \ - network \ sql \ # removed-by-refactor qtHaveModule(opengl): SUBDIRS += opengl qtHaveModule(dbus): SUBDIRS += dbus +qtHaveModule(network): SUBDIRS += network check-trusted.CONFIG += recursive QMAKE_EXTRA_TARGETS += check-trusted diff --git a/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.h b/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.h index 3c23a4d85b..d59678823d 100644 --- a/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.h +++ b/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.h @@ -44,8 +44,6 @@ #include <QtCore/qdir.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -93,6 +91,4 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemIterator::IteratorFlags) QT_END_NAMESPACE -QT_END_HEADER - #endif diff --git a/tests/benchmarks/corelib/tools/qvector/qrawvector.h b/tests/benchmarks/corelib/tools/qvector/qrawvector.h index 1bfc107d39..3f0d72a231 100644 --- a/tests/benchmarks/corelib/tools/qvector/qrawvector.h +++ b/tests/benchmarks/corelib/tools/qvector/qrawvector.h @@ -55,8 +55,6 @@ #include <stdlib.h> #include <string.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -752,6 +750,4 @@ Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(RawVector) QT_END_NAMESPACE -QT_END_HEADER - #endif // QRAWVECTOR_H diff --git a/tests/benchmarks/gui/image/image.pro b/tests/benchmarks/gui/image/image.pro index 2d5db35a73..71228f4499 100644 --- a/tests/benchmarks/gui/image/image.pro +++ b/tests/benchmarks/gui/image/image.pro @@ -6,5 +6,5 @@ SUBDIRS = \ qpixmap \ qpixmapcache -!qtHaveModule(widgets): SUBDIRS -= \ +!qtHaveModule(widgets)|!qtHaveModule(network): SUBDIRS -= \ qimagereader diff --git a/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp index e653e8dffb..f62ce6bf5c 100644 --- a/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -471,6 +471,10 @@ private slots: void httpDownloadPerformanceDownloadBuffer_data(); void httpDownloadPerformanceDownloadBuffer(); void httpsRequestChain(); + void httpsUpload(); + +private: + void runHttpsUploadRequest(const QByteArray &data, const QNetworkRequest &request); }; void tst_qnetworkreply::initTestCase() @@ -825,6 +829,28 @@ void tst_qnetworkreply::httpsRequestChain() } +void tst_qnetworkreply::runHttpsUploadRequest(const QByteArray &data, const QNetworkRequest &request) +{ + QNetworkReply* reply = manager.post(request, data); + reply->ignoreSslErrors(); + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(15); + QVERIFY(!QTestEventLoop::instance().timeout()); + QCOMPARE(reply->error(), QNetworkReply::NoError); + reply->deleteLater(); +} + +void tst_qnetworkreply::httpsUpload() +{ + QByteArray data = QByteArray(2*1024*1024+1, '\177'); + QNetworkRequest request(QUrl("https://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi")); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream"); +// for (int a = 0; a < 10; ++a) +// runHttpsUploadRequest(data, request); // to warmup all TCP connections + QBENCHMARK { + runHttpsUploadRequest(data, request); + } +} QTEST_MAIN(tst_qnetworkreply) diff --git a/tests/manual/dialogs/colordialogpanel.cpp b/tests/manual/dialogs/colordialogpanel.cpp new file mode 100644 index 0000000000..695e37a4c7 --- /dev/null +++ b/tests/manual/dialogs/colordialogpanel.cpp @@ -0,0 +1,261 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "colordialogpanel.h" + +#include <QGroupBox> +#include <QCheckBox> +#include <QPushButton> +#include <QVBoxLayout> +#include <QHBoxLayout> +#include <QMessageBox> +#include <QSortFilterProxyModel> +#include <QComboBox> +#include <QTimer> +#include <QDebug> + +// SVG color keyword names provided by the World Wide Web Consortium +static inline QStringList svgColorNames() +{ + return QStringList() + << "aliceblue" << "antiquewhite" << "aqua" << "aquamarine" << "azure" << "beige" << "bisque" + << "black" << "blanchedalmond" << "blue" << "blueviolet" << "brown" << "burlywood" << "cadetblue" + << "chartreuse" << "chocolate" << "coral" << "cornflowerblue" << "cornsilk" << "crimson" << "cyan" + << "darkblue" << "darkcyan" << "darkgoldenrod" << "darkgray" << "darkgreen" << "darkgrey" + << "darkkhaki" << "darkmagenta" << "darkolivegreen" << "darkorange" << "darkorchid" << "darkred" + << "darksalmon" << "darkseagreen" << "darkslateblue" << "darkslategray" << "darkslategrey" + << "darkturquoise" << "darkviolet" << "deeppink" << "deepskyblue" << "dimgray" << "dimgrey" + << "dodgerblue" << "firebrick" << "floralwhite" << "forestgreen" << "fuchsia" << "gainsboro" + << "ghostwhite" << "gold" << "goldenrod" << "gray" << "grey" << "green" << "greenyellow" + << "honeydew" << "hotpink" << "indianred" << "indigo" << "ivory" << "khaki" << "lavender" + << "lavenderblush" << "lawngreen" << "lemonchiffon" << "lightblue" << "lightcoral" << "lightcyan" + << "lightgoldenrodyellow" << "lightgray" << "lightgreen" << "lightgrey" << "lightpink" + << "lightsalmon" << "lightseagreen" << "lightskyblue" << "lightslategray" << "lightslategrey" + << "lightsteelblue" << "lightyellow" << "lime" << "limegreen" << "linen" << "magenta" + << "maroon" << "mediumaquamarine" << "mediumblue" << "mediumorchid" << "mediumpurple" + << "mediumseagreen" << "mediumslateblue" << "mediumspringgreen" << "mediumturquoise" + << "mediumvioletred" << "midnightblue" << "mintcream" << "mistyrose" << "moccasin" + << "navajowhite" << "navy" << "oldlace" << "olive" << "olivedrab" << "orange" << "orangered" + << "orchid" << "palegoldenrod" << "palegreen" << "paleturquoise" << "palevioletred" + << "papayawhip" << "peachpuff" << "peru" << "pink" << "plum" << "powderblue" << "purple" << "red" + << "rosybrown" << "royalblue" << "saddlebrown" << "salmon" << "sandybrown" << "seagreen" + << "seashell" << "sienna" << "silver" << "skyblue" << "slateblue" << "slategray" << "slategrey" + << "snow" << "springgreen" << "steelblue" << "tan" << "teal" << "thistle" << "tomato" + << "turquoise" << "violet" << "wheat" << "white" << "whitesmoke" << "yellow" << "yellowgreen"; +} + +static inline QPushButton *addButton(const QString &description, QVBoxLayout *layout, + QObject *receiver, const char *slotFunc) +{ + QPushButton *button = new QPushButton(description); + QObject::connect(button, SIGNAL(clicked()), receiver, slotFunc); + layout->addWidget(button); + return button; +} + +class ColorProxyModel : public QSortFilterProxyModel +{ +public: + ColorProxyModel(QObject *parent = 0) : QSortFilterProxyModel(parent) + { + } + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const + { + if (role == Qt::DisplayRole) { + QString name = data(index, Qt::EditRole).toString(); + return tr("%1 (%2)").arg(name, QColor(name).name()); + } + if (role == Qt::DecorationRole) + return QColor(data(index, Qt::EditRole).toString()); + return QSortFilterProxyModel::data(index, role); + } +}; + +ColorDialogPanel::ColorDialogPanel(QWidget *parent) + : QWidget(parent) + , m_colorComboBox(new QComboBox) + , m_showAlphaChannel(new QCheckBox(tr("Show alpha channel"))) + , m_noButtons(new QCheckBox(tr("Don't display OK/Cancel buttons"))) + , m_dontUseNativeDialog(new QCheckBox(tr("Don't use native dialog"))) +{ + // Options + QGroupBox *optionsGroupBox = new QGroupBox(tr("Options"), this); + QVBoxLayout *optionsLayout = new QVBoxLayout(optionsGroupBox); + optionsLayout->addWidget(m_showAlphaChannel); + optionsLayout->addWidget(m_noButtons); + optionsLayout->addWidget(m_dontUseNativeDialog); + + // Color + QGroupBox *colorGroupBox = new QGroupBox(tr("Color"), this); + QVBoxLayout *colorLayout = new QVBoxLayout(colorGroupBox); + colorLayout->addWidget(m_colorComboBox); + m_colorComboBox->addItems(svgColorNames()); + m_colorComboBox->setEditable(true); + + QAbstractItemModel *sourceModel = m_colorComboBox->model(); + ColorProxyModel* proxyModel = new ColorProxyModel(m_colorComboBox); + proxyModel->setSourceModel(sourceModel); + sourceModel->setParent(proxyModel); + m_colorComboBox->setModel(proxyModel); + + // Buttons + QGroupBox *buttonsGroupBox = new QGroupBox(tr("Show")); + QVBoxLayout *buttonsLayout = new QVBoxLayout(buttonsGroupBox); + addButton(tr("Exec modal"), buttonsLayout, this, SLOT(execModal())); + addButton(tr("Show modal"), buttonsLayout, this, SLOT(showModal())); + m_deleteModalDialogButton = + addButton(tr("Delete modal"), buttonsLayout, this, SLOT(deleteModalDialog())); + addButton(tr("Show non-modal"), buttonsLayout, this, SLOT(showNonModal())); + m_deleteNonModalDialogButton = + addButton(tr("Delete non-modal"), buttonsLayout, this, SLOT(deleteNonModalDialog())); + addButton(tr("Restore defaults"), buttonsLayout, this, SLOT(restoreDefaults())); + buttonsLayout->addStretch(); + + // Main layout + QHBoxLayout *mainLayout = new QHBoxLayout(this); + QVBoxLayout *leftLayout = new QVBoxLayout; + leftLayout->addWidget(optionsGroupBox); + leftLayout->addWidget(colorGroupBox); + leftLayout->addStretch(); + mainLayout->addLayout(leftLayout); + mainLayout->addWidget(buttonsGroupBox); + + enableDeleteModalDialogButton(); + enableDeleteNonModalDialogButton(); + restoreDefaults(); +} + +void ColorDialogPanel::execModal() +{ + QColorDialog dialog(this); + applySettings(&dialog); + connect(&dialog, SIGNAL(accepted()), this, SLOT(accepted())); + dialog.setWindowTitle(tr("Modal Color Dialog Qt %1").arg(QLatin1String(QT_VERSION_STR))); + dialog.exec(); +} + +void ColorDialogPanel::showModal() +{ + if (m_modalDialog.isNull()) { + static int n = 0; + m_modalDialog = new QColorDialog(this); + m_modalDialog->setModal(true); + connect(m_modalDialog.data(), SIGNAL(accepted()), this, SLOT(accepted())); + m_modalDialog->setWindowTitle(tr("Modal Color Dialog #%1 Qt %2") + .arg(++n) + .arg(QLatin1String(QT_VERSION_STR))); + enableDeleteModalDialogButton(); + } + applySettings(m_modalDialog); + m_modalDialog->show(); +} + +void ColorDialogPanel::showNonModal() +{ + if (m_nonModalDialog.isNull()) { + static int n = 0; + m_nonModalDialog = new QColorDialog(this); + connect(m_nonModalDialog.data(), SIGNAL(accepted()), this, SLOT(accepted())); + m_nonModalDialog->setWindowTitle(tr("Non-Modal Color Dialog #%1 Qt %2") + .arg(++n) + .arg(QLatin1String(QT_VERSION_STR))); + enableDeleteNonModalDialogButton(); + } + applySettings(m_nonModalDialog); + m_nonModalDialog->show(); +} + +void ColorDialogPanel::deleteNonModalDialog() +{ + if (!m_nonModalDialog.isNull()) + delete m_nonModalDialog; + enableDeleteNonModalDialogButton(); +} + +void ColorDialogPanel::deleteModalDialog() +{ + if (!m_modalDialog.isNull()) + delete m_modalDialog; + enableDeleteModalDialogButton(); +} + +void ColorDialogPanel::accepted() +{ + const QColorDialog *d = qobject_cast<const QColorDialog *>(sender()); + Q_ASSERT(d); + m_result.clear(); + QDebug(&m_result).nospace() + << "Current color: " << d->currentColor() + << "\nSelected color: " << d->selectedColor(); + QTimer::singleShot(0, this, SLOT(showAcceptedResult())); // Avoid problems with the closing (modal) dialog as parent. +} + +void ColorDialogPanel::showAcceptedResult() +{ + QMessageBox::information(this, tr("Color Dialog Accepted"), m_result, QMessageBox::Ok); +} + +void ColorDialogPanel::restoreDefaults() +{ + QColorDialog d; + m_showAlphaChannel->setChecked(d.testOption(QColorDialog::ShowAlphaChannel)); + m_noButtons->setChecked(d.testOption(QColorDialog::NoButtons)); + m_dontUseNativeDialog->setChecked(d.testOption(QColorDialog::DontUseNativeDialog)); +} + +void ColorDialogPanel::enableDeleteNonModalDialogButton() +{ + m_deleteNonModalDialogButton->setEnabled(!m_nonModalDialog.isNull()); +} + +void ColorDialogPanel::enableDeleteModalDialogButton() +{ + m_deleteModalDialogButton->setEnabled(!m_modalDialog.isNull()); +} + +void ColorDialogPanel::applySettings(QColorDialog *d) const +{ + d->setOption(QColorDialog::ShowAlphaChannel, m_showAlphaChannel->isChecked()); + d->setOption(QColorDialog::NoButtons, m_noButtons->isChecked()); + d->setOption(QColorDialog::DontUseNativeDialog, m_dontUseNativeDialog->isChecked()); + d->setCurrentColor(QColor(m_colorComboBox->itemData(m_colorComboBox->currentIndex(), Qt::EditRole).toString())); +} diff --git a/tests/manual/dialogs/colordialogpanel.h b/tests/manual/dialogs/colordialogpanel.h new file mode 100644 index 0000000000..bcd2cf6e52 --- /dev/null +++ b/tests/manual/dialogs/colordialogpanel.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef COLORDIALOGPANEL_H +#define COLORDIALOGPANEL_H + +#include <QPointer> +#include <QColorDialog> + +class QComboBox; +class QCheckBox; +class QPushButton; + +class ColorDialogPanel : public QWidget +{ + Q_OBJECT +public: + explicit ColorDialogPanel(QWidget *parent = 0); + +public slots: + void execModal(); + void showModal(); + void showNonModal(); + void deleteNonModalDialog(); + void deleteModalDialog(); + void accepted(); + void showAcceptedResult(); + void restoreDefaults(); + +private slots: + void enableDeleteNonModalDialogButton(); + void enableDeleteModalDialogButton(); + +private: + void applySettings(QColorDialog *d) const; + + QComboBox *m_colorComboBox; + QCheckBox *m_showAlphaChannel; + QCheckBox *m_noButtons; + QCheckBox *m_dontUseNativeDialog; + QPushButton *m_deleteNonModalDialogButton; + QPushButton *m_deleteModalDialogButton; + QString m_result; + QPointer<QColorDialog> m_modalDialog; + QPointer<QColorDialog> m_nonModalDialog; +}; + +#endif // COLORDIALOGPANEL_H diff --git a/tests/manual/dialogs/dialogs.pro b/tests/manual/dialogs/dialogs.pro index ff916d3854..fe40994241 100644 --- a/tests/manual/dialogs/dialogs.pro +++ b/tests/manual/dialogs/dialogs.pro @@ -4,5 +4,5 @@ greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = dialogs TEMPLATE = app -SOURCES += main.cpp filedialogpanel.cpp -HEADERS += filedialogpanel.h +SOURCES += main.cpp filedialogpanel.cpp colordialogpanel.cpp fontdialogpanel.cpp +HEADERS += filedialogpanel.h colordialogpanel.h fontdialogpanel.h diff --git a/tests/manual/dialogs/filedialogpanel.cpp b/tests/manual/dialogs/filedialogpanel.cpp index 66a5201db0..636e65b684 100644 --- a/tests/manual/dialogs/filedialogpanel.cpp +++ b/tests/manual/dialogs/filedialogpanel.cpp @@ -44,6 +44,7 @@ #include <QGridLayout> #include <QVBoxLayout> #include <QHBoxLayout> +#include <QGridLayout> #include <QFormLayout> #include <QSpacerItem> #include <QGroupBox> @@ -105,11 +106,13 @@ inline void setComboBoxValue(QComboBox *c, int v) c->setCurrentIndex(c->findData(QVariant(v))); } -static inline void addButton(const QString &description, QBoxLayout *layout, QObject *receiver, const char *slotFunc) +static inline QPushButton *addButton(const QString &description, QGridLayout *layout, + int &row, int column, QObject *receiver, const char *slotFunc) { QPushButton *button = new QPushButton(description); QObject::connect(button, SIGNAL(clicked()), receiver, slotFunc); - layout->addWidget(button); + layout->addWidget(button, row++, column); + return button; } // A line edit for editing the label fields of the dialog, keeping track of whether it has @@ -159,6 +162,8 @@ FileDialogPanel::FileDialogPanel(QWidget *parent) , m_selectedFileName(new QLineEdit(this)) , m_nameFilters(new QPlainTextEdit) , m_selectedNameFilter(new QLineEdit(this)) + , m_deleteNonModalDialogButton(0) + , m_deleteModalDialogButton(0) { // Options QGroupBox *optionsGroupBox = new QGroupBox(tr("Options")); @@ -197,19 +202,24 @@ FileDialogPanel::FileDialogPanel(QWidget *parent) labelsLayout->addRow(tr("Reject label:"), m_labelLineEdits.back()); // Buttons - QVBoxLayout *buttonLayout = new QVBoxLayout; - buttonLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding)); - addButton(tr("Show modal"), buttonLayout, this, SLOT(showModal())); - addButton(tr("Show non-modal"), buttonLayout, this, SLOT(showNonModal())); - addButton(tr("getOpenFileName"), buttonLayout, this, SLOT(getOpenFileName())); - addButton(tr("getOpenFileNames"), buttonLayout, this, SLOT(getOpenFileNames())); - addButton(tr("getSaveFileName"), buttonLayout, this, SLOT(getSaveFileName())); - addButton(tr("getExistingDirectory"), buttonLayout, this, SLOT(getExistingDirectory())); - addButton(tr("Restore defaults"), buttonLayout, this, SLOT(restoreDefaults())); QGroupBox *buttonsGroupBox = new QGroupBox(tr("Show")); - QHBoxLayout *buttonsGroupLayout = new QHBoxLayout(buttonsGroupBox); - buttonsGroupLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored)); - buttonsGroupLayout->addLayout(buttonLayout); + QGridLayout *buttonLayout = new QGridLayout(buttonsGroupBox); + int row = 0; + int column = 0; + addButton(tr("Exec modal"), buttonLayout, row, column, this, SLOT(execModal())); + addButton(tr("Show modal"), buttonLayout, row, column, this, SLOT(showModal())); + m_deleteModalDialogButton = + addButton(tr("Delete modal"), buttonLayout, row, column, this, SLOT(deleteModalDialog())); + addButton(tr("Show non-modal"), buttonLayout, row, column, this, SLOT(showNonModal())); + m_deleteNonModalDialogButton = + addButton(tr("Delete non-modal"), buttonLayout, row, column, this, SLOT(deleteNonModalDialog())); + row = 0; + column++; + addButton(tr("getOpenFileName"), buttonLayout, row, column, this, SLOT(getOpenFileName())); + addButton(tr("getOpenFileNames"), buttonLayout, row, column, this, SLOT(getOpenFileNames())); + addButton(tr("getSaveFileName"), buttonLayout, row, column, this, SLOT(getSaveFileName())); + addButton(tr("getExistingDirectory"), buttonLayout, row, column, this, SLOT(getExistingDirectory())); + addButton(tr("Restore defaults"), buttonLayout, row, column, this, SLOT(restoreDefaults())); // Main layout QGridLayout *gridLayout = new QGridLayout(this); @@ -218,26 +228,76 @@ FileDialogPanel::FileDialogPanel(QWidget *parent) gridLayout->addWidget(labelsGroupBox, 1, 0); gridLayout->addWidget(buttonsGroupBox, 1, 1); + enableDeleteModalDialogButton(); + enableDeleteNonModalDialogButton(); restoreDefaults(); } -void FileDialogPanel::showModal() +void FileDialogPanel::execModal() { QFileDialog dialog(this); applySettings(&dialog); + connect(&dialog, SIGNAL(accepted()), this, SLOT(accepted())); dialog.setWindowTitle(tr("Modal File Dialog Qt %1").arg(QLatin1String(QT_VERSION_STR))); dialog.exec(); } +void FileDialogPanel::showModal() +{ + if (m_modalDialog.isNull()) { + static int n = 0; + m_modalDialog = new QFileDialog(this); + m_modalDialog->setModal(true); + connect(m_modalDialog.data(), SIGNAL(accepted()), this, SLOT(accepted())); + m_modalDialog->setWindowTitle(tr("Modal File Dialog #%1 Qt %2") + .arg(++n) + .arg(QLatin1String(QT_VERSION_STR))); + enableDeleteModalDialogButton(); + } + applySettings(m_modalDialog); + m_modalDialog->show(); +} + void FileDialogPanel::showNonModal() { - QFileDialog *dialog = new QFileDialog(this); - dialog->setAttribute(Qt::WA_DeleteOnClose); - applySettings(dialog); - dialog->setWindowTitle(tr("Non-Modal File Dialog Qt %1").arg(QLatin1String(QT_VERSION_STR))); - dialog->show(); + if (m_nonModalDialog.isNull()) { + static int n = 0; + m_nonModalDialog = new QFileDialog(this); + connect(m_nonModalDialog.data(), SIGNAL(accepted()), this, SLOT(accepted())); + m_nonModalDialog->setWindowTitle(tr("Non-Modal File Dialog #%1 Qt %2") + .arg(++n) + .arg(QLatin1String(QT_VERSION_STR))); + enableDeleteNonModalDialogButton(); + } + applySettings(m_nonModalDialog); + m_nonModalDialog->show(); +} + +void FileDialogPanel::deleteNonModalDialog() +{ + if (!m_nonModalDialog.isNull()) + delete m_nonModalDialog; + enableDeleteNonModalDialogButton(); } +void FileDialogPanel::deleteModalDialog() +{ + if (!m_modalDialog.isNull()) + delete m_modalDialog; + enableDeleteModalDialogButton(); +} + +void FileDialogPanel::enableDeleteNonModalDialogButton() +{ + m_deleteNonModalDialogButton->setEnabled(!m_nonModalDialog.isNull()); +} + +void FileDialogPanel::enableDeleteModalDialogButton() +{ + m_deleteModalDialogButton->setEnabled(!m_modalDialog.isNull()); +} + + QString FileDialogPanel::filterString() const { return m_nameFilters->toPlainText().trimmed().replace(QLatin1String("\n"), QLatin1String(";;")); @@ -340,7 +400,9 @@ void FileDialogPanel::applySettings(QFileDialog *d) const d->setFileMode(comboBoxValue<QFileDialog::FileMode>(m_fileMode)); d->setOptions(options()); d->setDefaultSuffix(m_defaultSuffix->text().trimmed()); - d->setDirectory(m_directory->text().trimmed()); + const QString directory = m_directory->text().trimmed(); + if (!directory.isEmpty()) + d->setDirectory(directory); const QString file = m_selectedFileName->text().trimmed(); if (!file.isEmpty()) d->selectFile(file); @@ -350,7 +412,6 @@ void FileDialogPanel::applySettings(QFileDialog *d) const d->selectNameFilter(filter); foreach (LabelLineEdit *l, m_labelLineEdits) l->apply(d); - connect(d, SIGNAL(accepted()), this, SLOT(accepted())); } void FileDialogPanel::accepted() diff --git a/tests/manual/dialogs/filedialogpanel.h b/tests/manual/dialogs/filedialogpanel.h index 699d917e4d..7ee7cb3f60 100644 --- a/tests/manual/dialogs/filedialogpanel.h +++ b/tests/manual/dialogs/filedialogpanel.h @@ -44,7 +44,9 @@ #include <QGroupBox> #include <QFileDialog> +#include <QPointer> +class QPushButton; class QCheckBox; class QComboBox; class QLineEdit; @@ -58,8 +60,11 @@ public: explicit FileDialogPanel(QWidget *parent = 0); public slots: + void execModal(); void showModal(); void showNonModal(); + void deleteNonModalDialog(); + void deleteModalDialog(); void getOpenFileNames(); void getOpenFileName(); void getSaveFileName(); @@ -68,6 +73,10 @@ public slots: void showAcceptedResult(); void restoreDefaults(); +private slots: + void enableDeleteNonModalDialogButton(); + void enableDeleteModalDialogButton(); + private: QString filterString() const; QFileDialog::Options options() const; @@ -87,7 +96,11 @@ private: QList<LabelLineEdit *> m_labelLineEdits; QPlainTextEdit *m_nameFilters; QLineEdit *m_selectedNameFilter; + QPushButton *m_deleteNonModalDialogButton; + QPushButton *m_deleteModalDialogButton; QString m_result; + QPointer<QFileDialog> m_modalDialog; + QPointer<QFileDialog> m_nonModalDialog; }; #endif // FILEDIALOGPANEL_H diff --git a/tests/manual/dialogs/fontdialogpanel.cpp b/tests/manual/dialogs/fontdialogpanel.cpp new file mode 100644 index 0000000000..2bdbb0625a --- /dev/null +++ b/tests/manual/dialogs/fontdialogpanel.cpp @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "fontdialogpanel.h" + +#include <QGroupBox> +#include <QCheckBox> +#include <QPushButton> +#include <QVBoxLayout> +#include <QHBoxLayout> +#include <QMessageBox> +#include <QFontComboBox> +#include <QDoubleSpinBox> +#include <QTimer> +#include <QDebug> + +static inline QPushButton *addButton(const QString &description, QVBoxLayout *layout, + QObject *receiver, const char *slotFunc) +{ + QPushButton *button = new QPushButton(description); + QObject::connect(button, SIGNAL(clicked()), receiver, slotFunc); + layout->addWidget(button); + return button; +} + +FontDialogPanel::FontDialogPanel(QWidget *parent) + : QWidget(parent) + , m_fontFamilyBox(new QFontComboBox) + , m_fontSizeBox(new QDoubleSpinBox) + , m_noButtons(new QCheckBox(tr("Don't display OK/Cancel buttons"))) + , m_dontUseNativeDialog(new QCheckBox(tr("Don't use native dialog"))) +{ + // Options + QGroupBox *optionsGroupBox = new QGroupBox(tr("Options"), this); + QVBoxLayout *optionsLayout = new QVBoxLayout(optionsGroupBox); + optionsLayout->addWidget(m_noButtons); + optionsLayout->addWidget(m_dontUseNativeDialog); + + // Font + QGroupBox *fontGroupBox = new QGroupBox(tr("Font"), this); + QHBoxLayout *fontLayout = new QHBoxLayout(fontGroupBox); + fontLayout->addWidget(m_fontFamilyBox); + fontLayout->addWidget(m_fontSizeBox); + m_fontSizeBox->setValue(QFont().pointSizeF()); + + // Buttons + QGroupBox *buttonsGroupBox = new QGroupBox(tr("Show")); + QVBoxLayout *buttonsLayout = new QVBoxLayout(buttonsGroupBox); + addButton(tr("Exec modal"), buttonsLayout, this, SLOT(execModal())); + addButton(tr("Show modal"), buttonsLayout, this, SLOT(showModal())); + m_deleteModalDialogButton = + addButton(tr("Delete modal"), buttonsLayout, this, SLOT(deleteModalDialog())); + addButton(tr("Show non-modal"), buttonsLayout, this, SLOT(showNonModal())); + m_deleteNonModalDialogButton = + addButton(tr("Delete non-modal"), buttonsLayout, this, SLOT(deleteNonModalDialog())); + addButton(tr("Restore defaults"), buttonsLayout, this, SLOT(restoreDefaults())); + buttonsLayout->addStretch(); + + // Main layout + QHBoxLayout *mainLayout = new QHBoxLayout(this); + QVBoxLayout *leftLayout = new QVBoxLayout; + leftLayout->addWidget(optionsGroupBox); + leftLayout->addWidget(fontGroupBox); + leftLayout->addStretch(); + mainLayout->addLayout(leftLayout); + mainLayout->addWidget(buttonsGroupBox); + + enableDeleteModalDialogButton(); + enableDeleteNonModalDialogButton(); + restoreDefaults(); +} + +void FontDialogPanel::execModal() +{ + QFontDialog dialog(this); + applySettings(&dialog); + connect(&dialog, SIGNAL(accepted()), this, SLOT(accepted())); + dialog.setWindowTitle(tr("Modal Font Dialog Qt %1").arg(QLatin1String(QT_VERSION_STR))); + dialog.exec(); +} + +void FontDialogPanel::showModal() +{ + if (m_modalDialog.isNull()) { + static int n = 0; + m_modalDialog = new QFontDialog(this); + m_modalDialog->setModal(true); + connect(m_modalDialog.data(), SIGNAL(accepted()), this, SLOT(accepted())); + m_modalDialog->setWindowTitle(tr("Modal Font Dialog #%1 Qt %2") + .arg(++n) + .arg(QLatin1String(QT_VERSION_STR))); + enableDeleteModalDialogButton(); + } + applySettings(m_modalDialog); + m_modalDialog->show(); +} + +void FontDialogPanel::showNonModal() +{ + if (m_nonModalDialog.isNull()) { + static int n = 0; + m_nonModalDialog = new QFontDialog(this); + connect(m_nonModalDialog.data(), SIGNAL(accepted()), this, SLOT(accepted())); + m_nonModalDialog->setWindowTitle(tr("Non-Modal Font Dialog #%1 Qt %2") + .arg(++n) + .arg(QLatin1String(QT_VERSION_STR))); + enableDeleteNonModalDialogButton(); + } + applySettings(m_nonModalDialog); + m_nonModalDialog->show(); +} + +void FontDialogPanel::deleteNonModalDialog() +{ + if (!m_nonModalDialog.isNull()) + delete m_nonModalDialog; + enableDeleteNonModalDialogButton(); +} + +void FontDialogPanel::deleteModalDialog() +{ + if (!m_modalDialog.isNull()) + delete m_modalDialog; + enableDeleteModalDialogButton(); +} + +void FontDialogPanel::accepted() +{ + const QFontDialog *d = qobject_cast<const QFontDialog *>(sender()); + Q_ASSERT(d); + m_result.clear(); + QDebug(&m_result).nospace() + << "Current font: " << d->currentFont() + << "\nSelected font: " << d->selectedFont(); + QTimer::singleShot(0, this, SLOT(showAcceptedResult())); // Avoid problems with the closing (modal) dialog as parent. +} + +void FontDialogPanel::showAcceptedResult() +{ + QMessageBox::information(this, tr("Color Dialog Accepted"), m_result, QMessageBox::Ok); +} + +void FontDialogPanel::restoreDefaults() +{ + QFontDialog d; + m_noButtons->setChecked(d.testOption(QFontDialog::NoButtons)); + m_dontUseNativeDialog->setChecked(d.testOption(QFontDialog::DontUseNativeDialog)); + m_fontFamilyBox->setCurrentFont(QFont()); + m_fontSizeBox->setValue(QFont().pointSizeF()); +} + +void FontDialogPanel::enableDeleteNonModalDialogButton() +{ + m_deleteNonModalDialogButton->setEnabled(!m_nonModalDialog.isNull()); +} + +void FontDialogPanel::enableDeleteModalDialogButton() +{ + m_deleteModalDialogButton->setEnabled(!m_modalDialog.isNull()); +} + +void FontDialogPanel::applySettings(QFontDialog *d) const +{ + d->setOption(QFontDialog::NoButtons, m_noButtons->isChecked()); + d->setOption(QFontDialog::DontUseNativeDialog, m_dontUseNativeDialog->isChecked()); + + QFont font = m_fontFamilyBox->currentFont(); + font.setPointSizeF(m_fontSizeBox->value()); + d->setCurrentFont(font); +} diff --git a/tests/manual/dialogs/fontdialogpanel.h b/tests/manual/dialogs/fontdialogpanel.h new file mode 100644 index 0000000000..92f2b7313f --- /dev/null +++ b/tests/manual/dialogs/fontdialogpanel.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FONTDIALOGPANEL_H +#define FONTDIALOGPANEL_H + +#include <QPointer> +#include <QFontDialog> + +class QCheckBox; +class QPushButton; +class QFontComboBox; +class QDoubleSpinBox; + +class FontDialogPanel : public QWidget +{ + Q_OBJECT +public: + explicit FontDialogPanel(QWidget *parent = 0); + +public slots: + void execModal(); + void showModal(); + void showNonModal(); + void deleteNonModalDialog(); + void deleteModalDialog(); + void accepted(); + void showAcceptedResult(); + void restoreDefaults(); + +private slots: + void enableDeleteNonModalDialogButton(); + void enableDeleteModalDialogButton(); + +private: + void applySettings(QFontDialog *d) const; + + QFontComboBox *m_fontFamilyBox; + QDoubleSpinBox *m_fontSizeBox; + QCheckBox *m_noButtons; + QCheckBox *m_dontUseNativeDialog; + QPushButton *m_deleteNonModalDialogButton; + QPushButton *m_deleteModalDialogButton; + QString m_result; + QPointer<QFontDialog> m_modalDialog; + QPointer<QFontDialog> m_nonModalDialog; +}; + +#endif // FONTDIALOGPANEL_H diff --git a/tests/manual/dialogs/main.cpp b/tests/manual/dialogs/main.cpp index c1ea7b0d8f..f137df1f49 100644 --- a/tests/manual/dialogs/main.cpp +++ b/tests/manual/dialogs/main.cpp @@ -40,6 +40,8 @@ ****************************************************************************/ #include "filedialogpanel.h" +#include "colordialogpanel.h" +#include "fontdialogpanel.h" #include <QMainWindow> #include <QApplication> @@ -50,7 +52,6 @@ #include <QKeySequence> // Test for dialogs, allowing to play with all dialog options for implementing native dialogs. -// Currently, only QFileDialog is implemented. // Compiles with Qt 4.8 and Qt 5. class MainWindow : public QMainWindow { @@ -68,6 +69,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); QTabWidget *tabWidget = new QTabWidget; tabWidget->addTab(new FileDialogPanel, tr("QFileDialog")); + tabWidget->addTab(new ColorDialogPanel, tr("QColorDialog")); + tabWidget->addTab(new FontDialogPanel, tr("QFontDialog")); setCentralWidget(tabWidget); } diff --git a/tests/manual/lance/lance.pro b/tests/manual/lance/lance.pro index 177ca0e40e..430c9196e6 100644 --- a/tests/manual/lance/lance.pro +++ b/tests/manual/lance/lance.pro @@ -1,5 +1,6 @@ LANCELOT_DIR = $$PWD/../../auto/other/lancelot CONFIG+=console moc +CONFIG -= app_bundle TEMPLATE = app INCLUDEPATH += . $$LANCELOT_DIR QT += core-private gui-private widgets printsupport diff --git a/tests/manual/widgets/itemviews/qheaderview/qheaderviewtest1.cpp b/tests/manual/widgets/itemviews/qheaderview/qheaderviewtest1.cpp index 7a8c1d159d..b5aeb023f4 100644 --- a/tests/manual/widgets/itemviews/qheaderview/qheaderviewtest1.cpp +++ b/tests/manual/widgets/itemviews/qheaderview/qheaderviewtest1.cpp @@ -99,6 +99,9 @@ int main(int argc, char *argv[]) m.setRowCount(500); m.setColumnCount(250); tv.setModel(&m); + tv.setSelectionMode(QAbstractItemView::SingleSelection); + // Comment in the line below to test selection with keyboard (space) + // tv.setEditTriggers(QAbstractItemView::NoEditTriggers); SomeHandler handler(tv.horizontalHeader(), &tv); tv.horizontalHeader()->setDefaultSectionSize(30); tv.show(); diff --git a/tests/manual/widgets/qgraphicsview/rubberband/rubberbandtest.cpp b/tests/manual/widgets/qgraphicsview/rubberband/rubberbandtest.cpp index 186203e7d8..aec2479239 100644 --- a/tests/manual/widgets/qgraphicsview/rubberband/rubberbandtest.cpp +++ b/tests/manual/widgets/qgraphicsview/rubberband/rubberbandtest.cpp @@ -60,11 +60,12 @@ public: class MyGraphicsView : public QGraphicsView { - + Q_OBJECT public: - MyGraphicsView() : QGraphicsView() + MyGraphicsView(QWidget *w, QLabel *l) : QGraphicsView(w), rubberbandLabel(l) { setDragMode(QGraphicsView::RubberBandDrag); + connect(this, SIGNAL(rubberBandChanged(QRect, QPointF, QPointF)), this, SLOT(updateRubberbandInfo(QRect, QPointF, QPointF))); } protected: void mouseMoveEvent(QMouseEvent *event) @@ -81,26 +82,46 @@ protected: if (yglobal > bottomPos) verticalScrollBar()->setValue(verticalScrollBar()->value() + 10); } + +protected slots: + void updateRubberbandInfo(QRect r, QPointF from, QPointF to) + { + QString textToShow; + QDebug s(&textToShow); + s << r << from << to; + rubberbandLabel->setText(textToShow); + } +protected: + QLabel *rubberbandLabel; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); - MyGraphicsView v; + + QWidget w; + w.setLayout(new QVBoxLayout); + QLabel *l = new QLabel(&w); + MyGraphicsView *v = new MyGraphicsView(&w, l); + + w.layout()->addWidget(v); + w.layout()->addWidget(l); QGraphicsScene s(0.0, 0.0, 5000.0, 5000.0); - v.setScene(&s); - v.setInteractive(true); - v.setRubberBandSelectionMode(Qt::IntersectsItemBoundingRect); - s.addRect( (qreal) 0.0, 0.0, 1000.0, 50.0, QPen(),QBrush(QColor(0,0,255))); + v->setScene(&s); + v->setInteractive(true); + v->setRubberBandSelectionMode(Qt::IntersectsItemBoundingRect); for (int u = 0; u < 100; ++u) - for (int v = 0; v < 100; ++v) { + for (int n = 0; n < 100; ++n) { MyGraphicsItem *item = new MyGraphicsItem(); - item->setRect(QRectF(v * 80.0, u * 80.0, 50.0, 20.0)); + item->setRect(QRectF(n * 80.0, u * 80.0, 50.0, 20.0)); s.addItem(item); } - v.show(); + + w.show(); app.exec(); return 0; } + +#include "rubberbandtest.moc" diff --git a/tests/manual/windowflags/controls.cpp b/tests/manual/windowflags/controls.cpp index cad84617fc..422656ff03 100644 --- a/tests/manual/windowflags/controls.cpp +++ b/tests/manual/windowflags/controls.cpp @@ -123,8 +123,10 @@ Qt::WindowFlags HintControl::hints() const flags |= Qt::WindowMinimizeButtonHint; if (windowMaximizeButtonCheckBox->isChecked()) flags |= Qt::WindowMaximizeButtonHint; +#if QT_VERSION >= 0x050000 if (windowFullscreenButtonCheckBox->isChecked()) flags |= Qt::WindowFullscreenButtonHint; +#endif if (windowCloseButtonCheckBox->isChecked()) flags |= Qt::WindowCloseButtonHint; if (windowContextHelpButtonCheckBox->isChecked()) @@ -153,7 +155,9 @@ void HintControl::setHints(Qt::WindowFlags flags) windowSystemMenuCheckBox->setChecked(flags & Qt::WindowSystemMenuHint); windowMinimizeButtonCheckBox->setChecked(flags & Qt::WindowMinimizeButtonHint); windowMaximizeButtonCheckBox->setChecked(flags & Qt::WindowMaximizeButtonHint); +#if QT_VERSION >= 0x050000 windowFullscreenButtonCheckBox->setChecked(flags & Qt::WindowFullscreenButtonHint); +#endif windowCloseButtonCheckBox->setChecked(flags & Qt::WindowCloseButtonHint); windowContextHelpButtonCheckBox->setChecked(flags & Qt::WindowContextHelpButtonHint); windowShadeButtonCheckBox->setChecked(flags & Qt::WindowShadeButtonHint); |