./ 0000755 0000156 0000165 00000000000 12701153654 011101 5 ustar jenkins jenkins ./doc/ 0000755 0000156 0000165 00000000000 12701153654 011646 5 ustar jenkins jenkins ./doc/qt/ 0000755 0000156 0000165 00000000000 12701153654 012272 5 ustar jenkins jenkins ./doc/qt/qml/ 0000755 0000156 0000165 00000000000 12701153654 013063 5 ustar jenkins jenkins ./doc/qt/qml/connectivity-qml.qdocconf.in 0000644 0000156 0000165 00000003342 12701153654 020515 0 ustar jenkins jenkins project = Connectivity
description = Ubuntu Connectivity QML API
version = CONNECTIVITY_QT_VERSION_MAJOR@.@CONNECTIVITY_QT_VERSION_MINOR@
outputencoding = UTF-8
sourceencoding = UTF-8
# Bug in Qt5.2 qdoc, does not support absolute paths
# just have to hack this over and copy the files to BINARY_DIR
#sourcedirs = @CMAKE_CURRENT_SOURCE_DIR@/pages @CMAKE_CURRENT_SOURCE_DIR@/qml-api
#exampledirs = @CMAKE_SOURCE_DIR@/examples/
#imagedirs = @CMAKE_CURRENT_SOURCE_DIR@/../images
sourcedirs = pages qml-api
exampledirs = examples/
sources.fileextensions = "*.qdoc *.qml"
headers.fileextensions = "*.h"
examples.fileextensions = "*.js *.qml"
examples.imageextensions = "*.png *.jpeg *.jpg"
outputdir = @CMAKE_CURRENT_BINARY_DIR@/html
outputformat = HTML
outputprefixes = QML
outputprefixes.QML = qml-
HTML.templatedir = @CMAKE_CURRENT_SOURCE_DIR@/
HTML.nobreadcrumbs = "true"
HTML.stylesheets = \
css/reset.css \
css/qtquick.css \
css/base.css \
css/scratch.css
HTML.headerstyles = \
"\n" \
"\n" \
"\n" \
"\n"
HTML.postheader = \
"
\n" \
"
\n"
HTML.footer = \
"
\n" \
"\n" \
"\n"
./doc/qt/qml/css/ 0000755 0000156 0000165 00000000000 12701153654 013653 5 ustar jenkins jenkins ./doc/qt/qml/css/base.css 0000644 0000156 0000165 00000027067 12701153654 015313 0 ustar jenkins jenkins /**
* Ubuntu Developer base stylesheet
*
* A base stylesheet containing site-wide styles
*
* @project Ubuntu Developer
* @version 1.0
* @author Canonical Web Team: Steve Edwards
* @copyright 2011 Canonical Ltd.
*/
/**
* @section Global
*/
body {
font-family: 'Ubuntu', 'Ubuntu Beta', UbuntuBeta, Ubuntu, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, sans-serif;
font-size: 13px;
line-height: 1.4;
color: #333;
}
a {
color: #dd4814;
text-decoration: none;
outline: 0;
}
p, dl {
margin-bottom: 10px;
}
strong {
font-weight: bold;
}
em {
font-style: italic;
}
code{
padding: 10px;
font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'DejaVu Sans Mono', Courier, monospace;
background-color: #fdf6f2;
display: block;
margin-bottom: 10px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
}
h1 {
font-size: 36px;
line-height: 1.1;
margin-bottom: 20px;
}
article h1,
h2 {
font-size: 24px;
line-height: 1.2;
margin-bottom: 14px;
}
h3 {
font-size: 16px;
line-height: 1.3;
margin-bottom: 8px;
}
h4 {
font-weight: bold;
}
time {
color:#999;
}
/**
* @section Structure
*/
.header-login,
.header-navigation div,
.header-content div {
margin: 0 auto;
width: 940px;
}
.header-content h1{
background-color:#ffffff;
display:inline-block;
}
.header-content h2{
background-color:#ffffff;
display:table;
}
.header-login ul {
margin: 4px 0;
float: right;
}
.header-login li {
margin-right: 10px;
float: left;
}
.header-login a {
color: #333;
}
.header-navigation {
border-top: 2px solid #dd4814;
border-bottom: 2px solid #dd4814;
background-color: #fff;
height: 54px;
clear: right;
overflow: hidden;
}
.header-navigation nav ul {
border-right: 1px solid #dd4814;
float: right;
}
.header-navigation nav li {
border-left: 1px solid #dd4814;
float: left;
height: 54px;
}
.header-navigation nav a {
padding: 18px 14px 0;
font-size: 14px;
display: block;
height: 36px;
}
.header-navigation nav a:hover {
background-color: #fcece7;
}
.header-navigation nav .current_page_item a,
.header-navigation nav .current_page_parent a,
.header-navigation nav .current_page_ancestor a {
background-color: #dd4814;
color: #fff;
}
.header-navigation input {
margin: 12px 10px 0 10px;
padding: 5px;
border-top: 1px solid #a1a1a1;
border-right: 1px solid #e0e0e0;
border-bottom: 1px solid #fff;
border-left: 1px solid #e0e0e0;
width: 90px;
font-style: italic;
color: #ccc;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
-moz-box-shadow: inset 0 1px 1px #e0e0e0;
-webkit-box-shadow: inset 0 1px 1px #e0e0e0;
box-shadow: inset 0 1px 1px #e0e0e0;
}
.header-navigation h2 {
margin: 18px 0 0 6px;
text-transform: lowercase;
font-size: 22px;
color: #dd4814;
float: left;
}
.header-navigation .logo-ubuntu {
margin-top: 12px;
float: left;
}
.header-content .header-navigation-secondary {
margin-bottom: 40px;
padding: 0;
position: relative;
z-index: 2;
}
.header-navigation-secondary div {
padding: 0;
border: 2px solid #dd4814;
-moz-border-radius: 0px 0px 4px 4px;
-webkit-border-radius: 0px 0px 4px 4px;
border-radius: 0px 0px 4px 4px;
background: #fff;
border-top: 0px;
width: 936px;
}
.header-navigation-secondary nav li {
float: left;
}
.header-navigation-secondary nav li a {
color: #333;
display: block;
height: 25px;
padding: 8px 8px 0;
}
.header-navigation-secondary nav li:hover,
.header-navigation-secondary nav .current_page_item a {
background: url("../img/sec-nav-hover.gif");
}
.header-content {
padding-bottom: 30px;
border-bottom: 1px solid #e0e0e0;
-moz-box-shadow: 0 1px 3px #e0e0e0;
-webkit-box-shadow: 0 1px 3px #e0e0e0;
box-shadow: 0 1px 3px #e0e0e0;
margin-bottom: 3px;
position: relative;
overflow: hidden;
}
footer {
padding: 10px 10px 40px 10px;
position: relative;
-moz-border-radius: 0 0 4px 4px;
-webkit-border-radius: 0 0 4px 4px;
border-radius: 0 0 4px 4px;
font-size: 12px;
background: url("../img/background-footer.png") repeat scroll 0 0 #f7f6f5;
}
footer div {
margin: 0 auto;
padding: 0 10px;
width: 940px;
}
footer a {
color: #000;
}
footer nav ul {
margin: 10px 17px 30px 0;
width: 172px;
display: inline-block;
vertical-align: top;
height: auto;
zoom: 1;
*display: inline;
}
footer nav ul.last {
margin-right: 0;
}
footer nav li {
margin-bottom: 8px;
}
footer nav li:first-child {
font-weight: bold;
}
footer p {
margin-bottom: 0;
}
#content {
padding-top: 35px;
}
.arrow-nav {
display: none;
position: absolute;
top: -1px;
z-index: 3;
}
.shadow {
margin: 30px 0 3px 0;
border-bottom: 1px solid #e0e0e0;
-moz-box-shadow: 0 2px 3px #e0e0e0;
-webkit-box-shadow: 0 2px 3px #e0e0e0;
box-shadow: 0 2px 3px #e0e0e0;
height: 3px;
}
/**
* @section Site-wide
*/
#content h2{
font-size:24px;
}
.box-orange {
padding: 10px;
border: 3px solid #dd4814;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
}
.box-orange .link-action-small {
float: right;
margin: 0 0 0 20px;
}
.link-bug {
margin-left: 10px;
color: #999;
}
.link-action {
float: left;
margin-bottom: 20px;
padding: 8px 12px;
display: block;
background-color: #dd4814;
color: #fff;
-moz-border-radius: 20px;
-webkit-border-radius: 20px;
border-radius: 20px;
font-size: 16px;
line-height: 1.3;
border-top: 3px solid #e6633a;
border-bottom: 3px solid #c03d14;
}
.link-action2 {
float: left;
display: block;
color: #fff;
font-size: 16px;
line-height: 1.3;
}
.link-action2 span{
display:block;
float:left;
}
.link-action2 .cta-left{
background:url(../img/button-cta-left.png) no-repeat;
width:22px;
height:48px;
}
.link-action2 .cta-center{
background:url(../img/button-cta-slice.png) repeat-x;
line-height:45px;
height:48px;
}
.link-action2 .cta-right{
background:url(../img/button-cta-right.png) no-repeat;
width:22px;
height:48px;
}
.link-action-small {
float: left;
display: block;
color: #fff;
font-size: 16px;
}
.link-action-small span{
display:block;
float:left;
height:42px;
}
.link-action-small .cta-left{
background:url(../img/button-cta-left-small.png) no-repeat;
width:19px;
}
.link-action-small .cta-center{
background:url(../img/button-cta-slice-small.png) repeat-x;
line-height:42px;
}
.link-action-small .cta-right{
background:url(../img/button-cta-right-small.png) no-repeat;
width:19px;
}
.link-action:active {
position: relative;
top: 1px;
}
.link-action2:active {
position: relative;
top: 1px;
}
.link-action-small:active {
position: relative;
top: 1px;
}
.list-bullets li {
margin-bottom: 10px;
list-style: disc;
list-style-position: inside;
}
.box {
margin-bottom: 30px;
padding: 15px;
border: 1px solid #aea79f;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
}
.box-padded {
margin-bottom: 30px;
padding: 5px;
border: 2px solid #aea79f;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
background: url("../img/pattern-featured.gif") repeat scroll 0 0 #ebe9e7;
overflow: hidden;
}
.box-padded h3 {
margin: 5px 0 10px 5px;
}
.box-padded div {
padding: 10px;
border: 1px solid #aea79f;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
background-color: #fff;
overflow: hidden;
}
.box-padded li {
padding: 0 10px;
float: left;
width: 211px;
border-right: 1px dotted #aea79f;
}
.box-padded li.first {
padding: 0;
margin-bottom: 0;
}
.box-padded li.last {
border: 0;
width: 217px;
}
.box-padded img {
margin: 0 10px 50px 0;
float: left;
-moz-border-radius: 8px;
-webkit-border-radius: 8px;
border-radius: 8px;
}
.box-clear {
margin-bottom: 40px;
}
.box-clear .grid-4.first {
margin-right: 15px;
padding-right: 15px;
}
.box-clear .grid-4 {
margin-left: 0;
margin-right: 10px;
padding-right: 10px;
width: 298px;
}
.box-clear time {
display: block;
border-bottom: 1px dotted #aea79f;
padding-bottom: 10px;
margin-bottom: 10px;
}
.box-clear div.first {
border-right: 1px dotted #aea79f;
}
.box-clear a {
display: block;
}
.box-clear .rss {
background: url("../img/rss.jpg") no-repeat scroll 0 center;
padding-left: 20px;
}
.box-clear .location {
display: block;
margin-bottom: 1px;
}
.box-clear .last {
margin: 0;
padding-right: 0;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
width: 293px;
}
/* Widgets */
.ui-state-focus {
outline: none;
}
.ui-accordion {
border-bottom: 1px dotted #aea79f;
}
.ui-accordion a {
display: block;
}
.ui-accordion h3 {
margin-bottom: 0;
border-top: 1px dotted #aea79f;
position: relative;
font-size: 13px;
font-weight: bold;
}
.ui-accordion h3 a {
padding: 10px 0;
color: #333;
}
.ui-accordion h4 {
margin-bottom: 5px;
}
.ui-accordion div fieldset {
padding-bottom: 5px;
}
.ui-accordion div li,
.ui-accordion div input {
margin-bottom: 10px;
}
.ui-accordion .ui-icon {
position: absolute;
top: 15px;
right: 0;
display: block;
width: 8px;
height: 8px;
background: url("../img/icon-accordion-inactive.png") 0 0 no-repeat transparent;
}
.ui-accordion .ui-state-active .ui-icon {
background-image: url("../img/icon-accordion-active.png");
}
.ui-accordion .current_page_item a {
color: #333;
}
.container-tweet {
-moz-border-radius: 4px 4px 4px 4px;
-webkit-border-radius: 4px 4px 4px 4px;
border-radius: 4px 4px 4px 4px;
padding: 10px 10px 10px;
background-color: #f7f7f7;
}
.container-tweet .tweet-follow {
margin-top: 10px;
margin-bottom: -10px;
padding-left: 55px;
padding-bottom: 6px;
background: url("../img/tweet-follow.png") 0 5px no-repeat;
display: block;
}
.container-tweet .tweet-follow span {
font-size: 16px;
font-weight: bold;
line-height: 1.2;
display: block;
}
.tweet a {
display: inline;
}
.tweet .tweet_text {
padding: 10px;
background-color: #fff;
-moz-border-radius: 4px 4px 4px 4px;
-webkit-border-radius: 4px 4px 4px 4px;
border-radius: 4px 4px 4px 4px;
border: 1px solid #dd4814;
font-size: 16px;
display: block;
clear: both;
}
.tweet.tweet-small .tweet_text {
font-size: inherit;
}
.tweet .tweet_text a {
color: #333;
}
.tweet .tweet_time,
.tweet .tweet_user_and_time {
padding: 15px 0 10px 0;
position: relative;
top: -2px;
background: url("../img/tweet-arrow.png") no-repeat;
display: block;
}
.tweet .tweet_odd .tweet_time,
.tweet .tweet_odd .tweet_user_and_time {
background-position: right 0;
float: right;
}
.tweet .tweet_even .tweet_time,
.tweet .tweet_even .tweet_user_and_time {
background-position: left 0;
float: left;
}
/* Search */
#content .list-search li {
list-style-type:none;
border:0px;
margin-bottom: 15px;
padding-top: 15px;
}
/* Blog */
.blog-article #nav-single {
margin-top: 30px;
margin-bottom: 30px;
}
.blog-article #nav-single .nav-next {
float: right;
}
.blog-article article header .entry-meta {
margin-bottom: 20px;
}
.blog-article article .entry-meta {
color: #999;
}
.blog-article #respond form input[type="submit"] {
float: left;
cursor: pointer;
margin-bottom: 20px;
padding: 8px 12px;
display: block;
background-color: #dd4814;
color: #fff;
-moz-border-radius: 20px;
-webkit-border-radius: 20px;
border-radius: 20px;
font-size: 16px;
line-height: 1.3;
border-top: 3px solid #e6633a;
border-left: 3px solid #e6633a;
border-right: 3px solid #e6633a;
border-bottom: 3px solid #c03d14;
}
.blog-article #respond form input[type="submit"]:active {
position: relative;
top: 1px;
}
.alignnone{
float:left;
margin:10px 20px 10px 0;
}
.alignleft{
float:left;
margin:10px 20px 10px 0;
}
.alignright{
float:right;
margin:10px 0 10px 20px;
}
.aligncenter{
float:left;
margin:10px 20px 10px 0;
}
.entry-content h2, .entry-content h3{
margin-top:20px;
}
.entry-content ul li{
list-style-type: circle;
margin-left:16px;
}
.entry-content hr{
border:none;
border-top: 1px dotted #AEA79F;
}
./doc/qt/qml/css/scratch.css 0000644 0000156 0000165 00000001374 12701153654 016021 0 ustar jenkins jenkins body {
margin: 0;
}
div.toc ul {
padding: 0;
}
div.toc li {
margin-bottom: 3px;
}
h1.title {
font-size: 36px;
line-height: 1.1;
font-weight: normal;
}
h0, h2 {
font-size: 24px;
line-height: 1.2;
margin: 14px 0;
font-weight: normal;
display: block;
}
a:hover {
color: #dd4814;
text-decoration: underline;
outline: 0;
}
table, pre {
border-radius: 0;
}
.annotated td {
padding: 0.8em 1em 0.3em;
}
.wrapper {
width: 940px;
margin: 0 auto;
}
.main-content {
width: 668px;
position: relative;
left: 270px;
}
.title {
margin-left: -270px;
margin-top: 30px;
margin-bottom: 50px;
}
.toc {
margin-left: -270px;
font-size: 100%;
margin-bottom: 40px;
padding: 0;
z-index: 2;
position: absolute;
top: 100px;
width: 250px;
}
./doc/qt/qml/css/reset.css 0000644 0000156 0000165 00000001533 12701153654 015511 0 ustar jenkins jenkins /*
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.com/yui/license.html
version: 3.3.0
build: 3167
*/
html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;} ./doc/qt/qml/css/qtquick.css 0000644 0000156 0000165 00000031751 12701153654 016055 0 ustar jenkins jenkins @media screen
{
/* basic elements */
html
{
color: #000000;
background: #FFFFFF;
}
table
{
border-collapse: collapse;
border-spacing: 0;
}
fieldset, img
{
border: 0;
max-width:100%;
}
address, caption, cite, code, dfn, em, strong, th, var, optgroup
{
font-style: inherit;
font-weight: inherit;
}
del, ins
{
text-decoration: none;
}
ol li
{
list-style: decimal;
}
ul li
{
list-style: none;
}
caption, th
{
text-align: left;
}
h1.title
{
font-weight: bold;
font-size: 150%;
}
h0
{
font-weight: bold;
font-size: 130%;
}
h1, h2, h3, h4, h5, h6
{
font-size: 100%;
}
q:before, q:after
{
content: '';
}
abbr, acronym
{
border: 0;
font-variant: normal;
}
sup, sub
{
vertical-align: baseline;
}
tt, .qmlreadonly span, .qmldefault span
{
word-spacing:0.5em;
}
legend
{
color: #000000;
}
strong
{
font-weight: bold;
}
em
{
font-style: italic;
}
body
{
margin: 0 1.5em 0 1.5em;
font-family: ubuntu;
line-height: normal
}
a
{
color: #00732F;
text-decoration: none;
}
hr
{
background-color: #E6E6E6;
border: 1px solid #E6E6E6;
height: 1px;
width: 100%;
text-align: left;
margin: 1.5em 0 1.5em 0;
}
pre
{
border: 1px solid #DDDDDD;
-moz-border-radius: 0.7em 0.7em 0.7em 0.7em;
-webkit-border-radius: 0.7em 0.7em 0.7em 0.7em;
border-radius: 0.7em 0.7em 0.7em 0.7em;
padding: 1em 1em 1em 1em;
overflow-x: auto;
}
table, pre
{
-moz-border-radius: 0.7em 0.7em 0.7em 0.7em;
-webkit-border-radius: 0.7em 0.7em 0.7em 0.7em;
border-radius: 0.7em 0.7em 0.7em 0.7em;
background-color: #F6F6F6;
border: 1px solid #E6E6E6;
border-collapse: separate;
margin-bottom: 2.5em;
}
pre {
font-size: 90%;
display: block;
overflow:hidden;
}
thead
{
margin-top: 0.5em;
font-weight: bold
}
th
{
padding: 0.5em 1.5em 0.5em 1em;
background-color: #E1E1E1;
border-left: 1px solid #E6E6E6;
}
td
{
padding: 0.25em 1.5em 0.25em 1em;
}
td.rightAlign
{
padding: 0.25em 0.5em 0.25em 1em;
}
table tr.odd
{
border-left: 1px solid #E6E6E6;
background-color: #F6F6F6;
color: black;
}
table tr.even
{
border-left: 1px solid #E6E6E6;
background-color: #ffffff;
color: #202020;
}
div.float-left
{
float: left; margin-right: 2em
}
div.float-right
{
float: right; margin-left: 2em
}
span.comment
{
color: #008B00;
}
span.string, span.char
{
color: #000084;
}
span.number
{
color: #a46200;
}
span.operator
{
color: #202020;
}
span.keyword
{
color: #840000;
}
span.name
{
color: black
}
span.type
{
font-weight: bold
}
span.type a:visited
{
color: #0F5300;
}
span.preprocessor
{
color: #404040
}
/* end basic elements */
/* font style elements */
.heading
{
font-weight: bold;
font-size: 125%;
}
.subtitle
{
font-size: 110%
}
.small-subtitle
{
font-size: 100%
}
.red
{
color:red;
}
/* end font style elements */
/* global settings*/
.header, .footer
{
display: block;
clear: both;
overflow: hidden;
}
/* end global settings*/
/* header elements */
.header .qtref
{
color: #00732F;
font-weight: bold;
font-size: 130%;
}
.header .content
{
margin-left: 5px;
margin-top: 5px;
margin-bottom: 0.5em;
}
.header .breadcrumb
{
font-size: 90%;
padding: 0.5em 0 0.5em 1em;
margin: 0;
background-color: #fafafa;
height: 1.35em;
border-bottom: 1px solid #d1d1d1;
}
.header .breadcrumb ul
{
margin: 0;
padding: 0;
}
.header .content
{
word-wrap: break-word;
}
.header .breadcrumb ul li
{
float: left;
background: url(../images/breadcrumb.png) no-repeat 0 3px;
padding-left: 1.5em;
margin-left: 1.5em;
}
.header .breadcrumb ul li.last
{
font-weight: normal;
}
.header .breadcrumb ul li a
{
color: #00732F;
}
.header .breadcrumb ul li.first
{
background-image: none;
padding-left: 0;
margin-left: 0;
}
.header .content ol li {
background: none;
margin-bottom: 1.0em;
margin-left: 1.2em;
padding-left: 0
}
.header .content li
{
background: url(../images/bullet_sq.png) no-repeat 0 5px;
margin-bottom: 1em;
padding-left: 1.2em;
}
/* end header elements */
/* content elements */
.content h1
{
font-weight: bold;
font-size: 130%
}
.content h2
{
font-weight: bold;
font-size: 120%;
width: 100%;
}
.content h3
{
font-weight: bold;
font-size: 110%;
width: 100%;
}
.content table p
{
margin: 0
}
.content ul
{
padding-left: 2.5em;
}
.content li
{
padding-top: 0.25em;
padding-bottom: 0.25em;
}
.content ul img {
vertical-align: middle;
}
.content a:visited
{
color: #4c0033;
text-decoration: none;
}
.content a:visited:hover
{
color: #4c0033;
text-decoration: underline;
}
a:hover
{
color: #4c0033;
text-decoration: underline;
}
descr p a
{
text-decoration: underline;
}
.descr p a:visited
{
text-decoration: underline;
}
.alphaChar{
width:95%;
background-color:#F6F6F6;
border:1px solid #E6E6E6;
-moz-border-radius: 7px 7px 7px 7px;
border-radius: 7px 7px 7px 7px;
-webkit-border-radius: 7px 7px 7px 7px;
font-size:12pt;
padding-left:10px;
margin-top:10px;
margin-bottom:10px;
}
.flowList{
/*vertical-align:top;*/
/*margin:20px auto;*/
column-count:3;
-webkit-column-count:3;
-moz-column-count:3;
/*
column-width:100%;
-webkit-column-width:200px;
-col-column-width:200px;
*/
column-gap:41px;
-webkit-column-gap:41px;
-moz-column-gap:41px;
column-rule: 1px dashed #ccc;
-webkit-column-rule: 1px dashed #ccc;
-moz-column-rule: 1px dashed #ccc;
}
.flowList dl{
}
.flowList dd{
/*display:inline-block;*/
margin-left:10px;
min-width:250px;
line-height: 1.5;
min-width:100%;
min-height:15px;
}
.flowList dd a{
}
.mainContent
{
padding-left:5px;
}
.content .flowList p{
padding:0px;
}
.content .alignedsummary
{
margin: 15px;
}
.qmltype
{
text-align: center;
font-size: 120%;
}
.qmlreadonly
{
padding-left: 5px;
float: right;
color: #254117;
}
.qmldefault
{
padding-left: 5px;
float: right;
color: red;
}
.qmldoc
{
}
.generic .alphaChar{
margin-top:5px;
}
.generic .odd .alphaChar{
background-color: #F6F6F6;
}
.generic .even .alphaChar{
background-color: #FFFFFF;
}
.memItemRight{
padding: 0.25em 1.5em 0.25em 0;
}
.highlightedCode
{
margin: 1.0em;
}
.annotated td {
padding: 0.25em 0.5em 0.25em 0.5em;
}
.toc
{
font-size: 80%
}
.header .content .toc ul
{
padding-left: 0px;
}
.content .toc h3 {
border-bottom: 0px;
margin-top: 0px;
}
.content .toc h3 a:hover {
color: #00732F;
text-decoration: none;
}
.content .toc .level2
{
margin-left: 1.5em;
}
.content .toc .level3
{
margin-left: 3.0em;
}
.content ul li
{
background: url(../images/bullet_sq.png) no-repeat 0 0.7em;
padding-left: 1em
}
.content .toc li
{
background: url(../images/bullet_dn.png) no-repeat 0 5px;
padding-left: 1em
}
.relpage
{
-moz-border-radius: 7px 7px 7px 7px;
-webkit-border-radius: 7px 7px 7px 7px;
border-radius: 7px 7px 7px 7px;
border: 1px solid #DDDDDD;
padding: 25px 25px;
clear: both;
}
.relpage ul
{
float: none;
padding: 1.5em;
}
h3.fn, span.fn
{
-moz-border-radius:7px 7px 7px 7px;
-webkit-border-radius:7px 7px 7px 7px;
border-radius:7px 7px 7px 7px;
background-color: #F6F6F6;
border-width: 1px;
border-style: solid;
border-color: #E6E6E6;
font-weight: bold;
word-spacing:3px;
padding:3px 5px;
}
.functionIndex {
font-size:12pt;
word-spacing:10px;
margin-bottom:10px;
background-color: #F6F6F6;
border-width: 1px;
border-style: solid;
border-color: #E6E6E6;
-moz-border-radius: 7px 7px 7px 7px;
-webkit-border-radius: 7px 7px 7px 7px;
border-radius: 7px 7px 7px 7px;
width:100%;
}
.centerAlign
{
text-align:center;
}
.rightAlign
{
text-align:right;
}
.leftAlign
{
text-align:left;
}
.topAlign{
vertical-align:top
}
.functionIndex a{
display:inline-block;
}
/* end content elements */
/* footer elements */
.footer
{
color: #393735;
font-size: 0.75em;
text-align: center;
padding-top: 1.5em;
padding-bottom: 1em;
background-color: #E6E7E8;
margin: 0;
}
.footer p
{
margin: 0.25em
}
.small
{
font-size: 0.5em;
}
/* end footer elements */
.item {
float: left;
position: relative;
width: 100%;
overflow: hidden;
}
.item .primary {
margin-right: 220px;
position: relative;
}
.item hr {
margin-left: -220px;
}
.item .secondary {
float: right;
width: 200px;
position: relative;
}
.item .cols {
clear: both;
display: block;
}
.item .cols .col {
float: left;
margin-left: 1.5%;
}
.item .cols .col.first {
margin-left: 0;
}
.item .cols.two .col {
width: 45%;
}
.item .box {
margin: 0 0 10px 0;
}
.item .box h3 {
margin: 0 0 10px 0;
}
.cols.unclear {
clear:none;
}
}
/* end of screen media */
/* start of print media */
@media print
{
input, textarea, .header, .footer, .toolbar, .feedback, .wrapper .hd, .wrapper .bd .sidebar, .wrapper .ft, #feedbackBox, #blurpage, .toc, .breadcrumb, .toolbar, .floatingResult
{
display: none;
background: none;
}
.content
{
background: none;
display: block;
width: 100%; margin: 0; float: none;
}
}
/* end of print media */
/* modify the TOC layouts */
div.toc ul {
padding-left: 20px;
}
div.toc li {
padding-left: 4px;
}
/* Remove the border around images*/
a img
{
border:none;
}
/*Add styling to the front pages*/
.threecolumn_area
{
padding-top: 20px;
padding-bottom: 20px;
}
.threecolumn_piece
{
display: inline-block;
margin-left: 78px;
margin-top: 8px;
padding: 0;
vertical-align: top;
width: 25.5%;
}
div.threecolumn_piece ul {
list-style-type: none;
padding-left: 0px;
margin-top: 2px;
}
div.threecolumn_piece p {
margin-bottom: 7px;
color: #5C626E;
text-decoration: none;
font-weight: bold;
}
div.threecolumn_piece li {
padding-left: 0px;
margin-bottom: 5px;
}
div.threecolumn_piece a {
font-weight: normal;
}
/* Add style to guide page*/
.fourcolumn_area
{
padding-top: 20px;
padding-bottom: 20px;
}
.fourcolumn_piece
{
display: inline-block;
margin-left: 35px;
margin-top: 8px;
padding: 0;
vertical-align: top;
width: 21.3%;
}
div.fourcolumn_piece ul {
list-style-type: none;
padding-left: 0px;
margin-top: 2px;
}
div.fourcolumn_piece p {
margin-bottom: 7px;
color: #40444D;
text-decoration: none;
font-weight: bold;
}
div.fourcolumn_piece li {
padding-left: 0px;
margin-bottom: 5px;
}
div.fourcolumn_piece a {
font-weight: normal;
}
./doc/qt/qml/CMakeLists.txt 0000644 0000156 0000165 00000002462 12701153654 015627 0 ustar jenkins jenkins set(DOC_SOURCES
examples/example_networking_status.qml
qml-api/NetworkingStatus.qml
pages/mainpage.qdoc)
# add a target to generate API documentation with qdoc
FIND_PROGRAM(QDOC_EXECUTABLE qdoc)
if(QDOC_EXECUTABLE)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/connectivity-qml.qdocconf.in"
"${CMAKE_CURRENT_BINARY_DIR}/connectivity-qml.qdocconf"
@ONLY
)
add_custom_target(qmldoc
ALL
COMMAND "${QDOC_EXECUTABLE}" "${CMAKE_CURRENT_BINARY_DIR}/connectivity-qml.qdocconf"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
COMMENT "Generating QML API documentation with qdoc" VERBATIM
DEPENDS ${DOC_SOURCES}
)
# copy stylesheet files into build directory for shadow builds
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/css"
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
)
# copy the API files over ot the build directery as there is a
# bug in qt5.2 qdoc for handling absolute paths
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qml-api"
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
)
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/pages"
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
)
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/examples"
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
)
install(
DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/
DESTINATION ${INSTALL_DOCDIR}/qml/html/
)
endif(QDOC_EXECUTABLE)
./doc/qt/qml/qml-api/ 0000755 0000156 0000165 00000000000 12701153654 014423 5 ustar jenkins jenkins ./doc/qt/qml/qml-api/NetworkingStatus.qml 0000644 0000156 0000165 00000004547 12701153654 020503 0 ustar jenkins jenkins /*
* Copyright © 2014 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
* Authors:
* Antti Kaijanmäki
*/
import QtQuick 2.0
/*!
\qmltype NetworkingStatus
\ingroup connectivity
\brief Overall system networking status.
This is the top-level class for accessing networking information.
This class inherits the Qt C++ ubuntu::connectivity::NetworkingStatus
and provides two utility properties online and limitedBandwith for easier
QML usage.
This object is exposed as a singleton.
\b{note:}
Using this component in confined application requires \e{connectivity} policy group.
\quotefile example_networking_status.qml
*/
QtObject {
/*!
\qmlproperty bool NetworkingStatus::online
\b{true} if system has Internet connection.
shorthand for C++:
\code
networkingStatus->status() == NetworkingStatus::Online
\endcode
*/
property bool online
/*!
\qmlproperty bool NetworkingStatus::limitedBandwith
\b{true} if Internet connection is bandwith limited.
shorthand for C++:
\code
networkingStatus->limitations().contains(NetworkingStatus::Limitations::Bandwith)
\endcode
*/
property bool limitedBandwith
/*!
\qmlproperty list NetworkingStatus::limitations
*/
property list limitations
/*!
\qmlproperty NetworkingStatus::Status status
status property of the base C++ class.
\code
onStatusChanged: {
if (status === NetworkingStatus::Offline)
;
else if (status === NetworkingStatus::Connecting)
;
else if (status === NetworkingStatus::Online)
;
}
\endcode
*/
property Status status
}
./doc/qt/qml/pages/ 0000755 0000156 0000165 00000000000 12701153654 014162 5 ustar jenkins jenkins ./doc/qt/qml/pages/mainpage.qdoc 0000644 0000156 0000165 00000001155 12701153654 016615 0 ustar jenkins jenkins /*!
\page index.html overview
\title Ubuntu Connectivity API
\contentspage {Ubuntu Connectivity API} {Contents}
\part Introduction
Ubuntu Connectivity API offers a way to access the connectivity related information of the system.
Qt C++ API version of this API also exists (see the C++ documentation).
\part Components
Available through:
\code
import Ubuntu.Connectivity 1.0
\endcode
\part Items
\annotatedlist connectivity
\part Reporting Bugs
If you find any problems with the or this documentation,
please file a bug in Connectivity API \l {https://bugs.launchpad.net/connectivity-api} {Launchpad page}.
*/
./doc/qt/qml/examples/ 0000755 0000156 0000165 00000000000 12701153654 014701 5 ustar jenkins jenkins ./doc/qt/qml/examples/example_networking_status.qml 0000644 0000156 0000165 00000003750 12701153654 022726 0 ustar jenkins jenkins /*
* Copyright (C) 2014 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
import QtQuick 2.0
import Ubuntu.Components 0.1
import Ubuntu.Connectivity 1.0
MainView {
id: root
objectName: "mainView"
applicationName: "Connectivity"
width: units.gu(100)
height: units.gu(75)
property real margins: units.gu(2)
property real buttonWidth: units.gu(9)
property var statusMap: ["Offline", "Connecting", "Online"]
Connections {
target: Connectivity
// full status can be retrieved from the base C++ class
// status property
onStatusChanged: console.log("Status: " + statusMap[Connectivity.status])
onOnlineChanged: console.log("Online: " + Connectivity.online)
}
Page {
title: i18n.tr("Networking Status")
Column {
anchors.centerIn: parent
Label {
// use the online property
text: Connectivity.online ? "Online" : "Not online"
fontSize: "large"
}
Label {
// use the status property
text: "Status: " + statusMap[Connectivity.status]
fontSize: "large"
}
Label {
// use the limitedBandwith property
text: Connectivity.limitedBandwith ? "Bandwith limited" : "Bandwith not limited"
fontSize: "large"
}
}
}
}
./doc/qt/CMakeLists.txt 0000644 0000156 0000165 00000000055 12701153654 015032 0 ustar jenkins jenkins add_subdirectory(cpp)
add_subdirectory(qml)
./doc/qt/cpp/ 0000755 0000156 0000165 00000000000 12701153654 013054 5 ustar jenkins jenkins ./doc/qt/cpp/ubuntu-appdev-site-header.html 0000644 0000156 0000165 00000002553 12701153654 020736 0 ustar jenkins jenkins
\n"
./doc/qt/cpp/ubuntu-appdev-site-footer.html 0000644 0000156 0000165 00000006444 12701153654 021007 0 ustar jenkins jenkins
\n"
./doc/qt/cpp/css/ 0000755 0000156 0000165 00000000000 12701153654 013644 5 ustar jenkins jenkins ./doc/qt/cpp/css/base.css 0000644 0000156 0000165 00000027067 12701153654 015304 0 ustar jenkins jenkins /**
* Ubuntu Developer base stylesheet
*
* A base stylesheet containing site-wide styles
*
* @project Ubuntu Developer
* @version 1.0
* @author Canonical Web Team: Steve Edwards
* @copyright 2011 Canonical Ltd.
*/
/**
* @section Global
*/
body {
font-family: 'Ubuntu', 'Ubuntu Beta', UbuntuBeta, Ubuntu, 'Bitstream Vera Sans', 'DejaVu Sans', Tahoma, sans-serif;
font-size: 13px;
line-height: 1.4;
color: #333;
}
a {
color: #dd4814;
text-decoration: none;
outline: 0;
}
p, dl {
margin-bottom: 10px;
}
strong {
font-weight: bold;
}
em {
font-style: italic;
}
code{
padding: 10px;
font-family: 'Ubuntu Mono', 'Consolas', 'Monaco', 'DejaVu Sans Mono', Courier, monospace;
background-color: #fdf6f2;
display: block;
margin-bottom: 10px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
}
h1 {
font-size: 36px;
line-height: 1.1;
margin-bottom: 20px;
}
article h1,
h2 {
font-size: 24px;
line-height: 1.2;
margin-bottom: 14px;
}
h3 {
font-size: 16px;
line-height: 1.3;
margin-bottom: 8px;
}
h4 {
font-weight: bold;
}
time {
color:#999;
}
/**
* @section Structure
*/
.header-login,
.header-navigation div,
.header-content div {
margin: 0 auto;
width: 940px;
}
.header-content h1{
background-color:#ffffff;
display:inline-block;
}
.header-content h2{
background-color:#ffffff;
display:table;
}
.header-login ul {
margin: 4px 0;
float: right;
}
.header-login li {
margin-right: 10px;
float: left;
}
.header-login a {
color: #333;
}
.header-navigation {
border-top: 2px solid #dd4814;
border-bottom: 2px solid #dd4814;
background-color: #fff;
height: 54px;
clear: right;
overflow: hidden;
}
.header-navigation nav ul {
border-right: 1px solid #dd4814;
float: right;
}
.header-navigation nav li {
border-left: 1px solid #dd4814;
float: left;
height: 54px;
}
.header-navigation nav a {
padding: 18px 14px 0;
font-size: 14px;
display: block;
height: 36px;
}
.header-navigation nav a:hover {
background-color: #fcece7;
}
.header-navigation nav .current_page_item a,
.header-navigation nav .current_page_parent a,
.header-navigation nav .current_page_ancestor a {
background-color: #dd4814;
color: #fff;
}
.header-navigation input {
margin: 12px 10px 0 10px;
padding: 5px;
border-top: 1px solid #a1a1a1;
border-right: 1px solid #e0e0e0;
border-bottom: 1px solid #fff;
border-left: 1px solid #e0e0e0;
width: 90px;
font-style: italic;
color: #ccc;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
-moz-box-shadow: inset 0 1px 1px #e0e0e0;
-webkit-box-shadow: inset 0 1px 1px #e0e0e0;
box-shadow: inset 0 1px 1px #e0e0e0;
}
.header-navigation h2 {
margin: 18px 0 0 6px;
text-transform: lowercase;
font-size: 22px;
color: #dd4814;
float: left;
}
.header-navigation .logo-ubuntu {
margin-top: 12px;
float: left;
}
.header-content .header-navigation-secondary {
margin-bottom: 40px;
padding: 0;
position: relative;
z-index: 2;
}
.header-navigation-secondary div {
padding: 0;
border: 2px solid #dd4814;
-moz-border-radius: 0px 0px 4px 4px;
-webkit-border-radius: 0px 0px 4px 4px;
border-radius: 0px 0px 4px 4px;
background: #fff;
border-top: 0px;
width: 936px;
}
.header-navigation-secondary nav li {
float: left;
}
.header-navigation-secondary nav li a {
color: #333;
display: block;
height: 25px;
padding: 8px 8px 0;
}
.header-navigation-secondary nav li:hover,
.header-navigation-secondary nav .current_page_item a {
background: url("../img/sec-nav-hover.gif");
}
.header-content {
padding-bottom: 30px;
border-bottom: 1px solid #e0e0e0;
-moz-box-shadow: 0 1px 3px #e0e0e0;
-webkit-box-shadow: 0 1px 3px #e0e0e0;
box-shadow: 0 1px 3px #e0e0e0;
margin-bottom: 3px;
position: relative;
overflow: hidden;
}
footer {
padding: 10px 10px 40px 10px;
position: relative;
-moz-border-radius: 0 0 4px 4px;
-webkit-border-radius: 0 0 4px 4px;
border-radius: 0 0 4px 4px;
font-size: 12px;
background: url("../img/background-footer.png") repeat scroll 0 0 #f7f6f5;
}
footer div {
margin: 0 auto;
padding: 0 10px;
width: 940px;
}
footer a {
color: #000;
}
footer nav ul {
margin: 10px 17px 30px 0;
width: 172px;
display: inline-block;
vertical-align: top;
height: auto;
zoom: 1;
*display: inline;
}
footer nav ul.last {
margin-right: 0;
}
footer nav li {
margin-bottom: 8px;
}
footer nav li:first-child {
font-weight: bold;
}
footer p {
margin-bottom: 0;
}
#content {
padding-top: 35px;
}
.arrow-nav {
display: none;
position: absolute;
top: -1px;
z-index: 3;
}
.shadow {
margin: 30px 0 3px 0;
border-bottom: 1px solid #e0e0e0;
-moz-box-shadow: 0 2px 3px #e0e0e0;
-webkit-box-shadow: 0 2px 3px #e0e0e0;
box-shadow: 0 2px 3px #e0e0e0;
height: 3px;
}
/**
* @section Site-wide
*/
#content h2{
font-size:24px;
}
.box-orange {
padding: 10px;
border: 3px solid #dd4814;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
}
.box-orange .link-action-small {
float: right;
margin: 0 0 0 20px;
}
.link-bug {
margin-left: 10px;
color: #999;
}
.link-action {
float: left;
margin-bottom: 20px;
padding: 8px 12px;
display: block;
background-color: #dd4814;
color: #fff;
-moz-border-radius: 20px;
-webkit-border-radius: 20px;
border-radius: 20px;
font-size: 16px;
line-height: 1.3;
border-top: 3px solid #e6633a;
border-bottom: 3px solid #c03d14;
}
.link-action2 {
float: left;
display: block;
color: #fff;
font-size: 16px;
line-height: 1.3;
}
.link-action2 span{
display:block;
float:left;
}
.link-action2 .cta-left{
background:url(../img/button-cta-left.png) no-repeat;
width:22px;
height:48px;
}
.link-action2 .cta-center{
background:url(../img/button-cta-slice.png) repeat-x;
line-height:45px;
height:48px;
}
.link-action2 .cta-right{
background:url(../img/button-cta-right.png) no-repeat;
width:22px;
height:48px;
}
.link-action-small {
float: left;
display: block;
color: #fff;
font-size: 16px;
}
.link-action-small span{
display:block;
float:left;
height:42px;
}
.link-action-small .cta-left{
background:url(../img/button-cta-left-small.png) no-repeat;
width:19px;
}
.link-action-small .cta-center{
background:url(../img/button-cta-slice-small.png) repeat-x;
line-height:42px;
}
.link-action-small .cta-right{
background:url(../img/button-cta-right-small.png) no-repeat;
width:19px;
}
.link-action:active {
position: relative;
top: 1px;
}
.link-action2:active {
position: relative;
top: 1px;
}
.link-action-small:active {
position: relative;
top: 1px;
}
.list-bullets li {
margin-bottom: 10px;
list-style: disc;
list-style-position: inside;
}
.box {
margin-bottom: 30px;
padding: 15px;
border: 1px solid #aea79f;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
}
.box-padded {
margin-bottom: 30px;
padding: 5px;
border: 2px solid #aea79f;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
background: url("../img/pattern-featured.gif") repeat scroll 0 0 #ebe9e7;
overflow: hidden;
}
.box-padded h3 {
margin: 5px 0 10px 5px;
}
.box-padded div {
padding: 10px;
border: 1px solid #aea79f;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
background-color: #fff;
overflow: hidden;
}
.box-padded li {
padding: 0 10px;
float: left;
width: 211px;
border-right: 1px dotted #aea79f;
}
.box-padded li.first {
padding: 0;
margin-bottom: 0;
}
.box-padded li.last {
border: 0;
width: 217px;
}
.box-padded img {
margin: 0 10px 50px 0;
float: left;
-moz-border-radius: 8px;
-webkit-border-radius: 8px;
border-radius: 8px;
}
.box-clear {
margin-bottom: 40px;
}
.box-clear .grid-4.first {
margin-right: 15px;
padding-right: 15px;
}
.box-clear .grid-4 {
margin-left: 0;
margin-right: 10px;
padding-right: 10px;
width: 298px;
}
.box-clear time {
display: block;
border-bottom: 1px dotted #aea79f;
padding-bottom: 10px;
margin-bottom: 10px;
}
.box-clear div.first {
border-right: 1px dotted #aea79f;
}
.box-clear a {
display: block;
}
.box-clear .rss {
background: url("../img/rss.jpg") no-repeat scroll 0 center;
padding-left: 20px;
}
.box-clear .location {
display: block;
margin-bottom: 1px;
}
.box-clear .last {
margin: 0;
padding-right: 0;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
width: 293px;
}
/* Widgets */
.ui-state-focus {
outline: none;
}
.ui-accordion {
border-bottom: 1px dotted #aea79f;
}
.ui-accordion a {
display: block;
}
.ui-accordion h3 {
margin-bottom: 0;
border-top: 1px dotted #aea79f;
position: relative;
font-size: 13px;
font-weight: bold;
}
.ui-accordion h3 a {
padding: 10px 0;
color: #333;
}
.ui-accordion h4 {
margin-bottom: 5px;
}
.ui-accordion div fieldset {
padding-bottom: 5px;
}
.ui-accordion div li,
.ui-accordion div input {
margin-bottom: 10px;
}
.ui-accordion .ui-icon {
position: absolute;
top: 15px;
right: 0;
display: block;
width: 8px;
height: 8px;
background: url("../img/icon-accordion-inactive.png") 0 0 no-repeat transparent;
}
.ui-accordion .ui-state-active .ui-icon {
background-image: url("../img/icon-accordion-active.png");
}
.ui-accordion .current_page_item a {
color: #333;
}
.container-tweet {
-moz-border-radius: 4px 4px 4px 4px;
-webkit-border-radius: 4px 4px 4px 4px;
border-radius: 4px 4px 4px 4px;
padding: 10px 10px 10px;
background-color: #f7f7f7;
}
.container-tweet .tweet-follow {
margin-top: 10px;
margin-bottom: -10px;
padding-left: 55px;
padding-bottom: 6px;
background: url("../img/tweet-follow.png") 0 5px no-repeat;
display: block;
}
.container-tweet .tweet-follow span {
font-size: 16px;
font-weight: bold;
line-height: 1.2;
display: block;
}
.tweet a {
display: inline;
}
.tweet .tweet_text {
padding: 10px;
background-color: #fff;
-moz-border-radius: 4px 4px 4px 4px;
-webkit-border-radius: 4px 4px 4px 4px;
border-radius: 4px 4px 4px 4px;
border: 1px solid #dd4814;
font-size: 16px;
display: block;
clear: both;
}
.tweet.tweet-small .tweet_text {
font-size: inherit;
}
.tweet .tweet_text a {
color: #333;
}
.tweet .tweet_time,
.tweet .tweet_user_and_time {
padding: 15px 0 10px 0;
position: relative;
top: -2px;
background: url("../img/tweet-arrow.png") no-repeat;
display: block;
}
.tweet .tweet_odd .tweet_time,
.tweet .tweet_odd .tweet_user_and_time {
background-position: right 0;
float: right;
}
.tweet .tweet_even .tweet_time,
.tweet .tweet_even .tweet_user_and_time {
background-position: left 0;
float: left;
}
/* Search */
#content .list-search li {
list-style-type:none;
border:0px;
margin-bottom: 15px;
padding-top: 15px;
}
/* Blog */
.blog-article #nav-single {
margin-top: 30px;
margin-bottom: 30px;
}
.blog-article #nav-single .nav-next {
float: right;
}
.blog-article article header .entry-meta {
margin-bottom: 20px;
}
.blog-article article .entry-meta {
color: #999;
}
.blog-article #respond form input[type="submit"] {
float: left;
cursor: pointer;
margin-bottom: 20px;
padding: 8px 12px;
display: block;
background-color: #dd4814;
color: #fff;
-moz-border-radius: 20px;
-webkit-border-radius: 20px;
border-radius: 20px;
font-size: 16px;
line-height: 1.3;
border-top: 3px solid #e6633a;
border-left: 3px solid #e6633a;
border-right: 3px solid #e6633a;
border-bottom: 3px solid #c03d14;
}
.blog-article #respond form input[type="submit"]:active {
position: relative;
top: 1px;
}
.alignnone{
float:left;
margin:10px 20px 10px 0;
}
.alignleft{
float:left;
margin:10px 20px 10px 0;
}
.alignright{
float:right;
margin:10px 0 10px 20px;
}
.aligncenter{
float:left;
margin:10px 20px 10px 0;
}
.entry-content h2, .entry-content h3{
margin-top:20px;
}
.entry-content ul li{
list-style-type: circle;
margin-left:16px;
}
.entry-content hr{
border:none;
border-top: 1px dotted #AEA79F;
}
./doc/qt/cpp/css/scratch.css 0000644 0000156 0000165 00000001374 12701153654 016012 0 ustar jenkins jenkins body {
margin: 0;
}
div.toc ul {
padding: 0;
}
div.toc li {
margin-bottom: 3px;
}
h1.title {
font-size: 36px;
line-height: 1.1;
font-weight: normal;
}
h0, h2 {
font-size: 24px;
line-height: 1.2;
margin: 14px 0;
font-weight: normal;
display: block;
}
a:hover {
color: #dd4814;
text-decoration: underline;
outline: 0;
}
table, pre {
border-radius: 0;
}
.annotated td {
padding: 0.8em 1em 0.3em;
}
.wrapper {
width: 940px;
margin: 0 auto;
}
.main-content {
width: 668px;
position: relative;
left: 270px;
}
.title {
margin-left: -270px;
margin-top: 30px;
margin-bottom: 50px;
}
.toc {
margin-left: -270px;
font-size: 100%;
margin-bottom: 40px;
padding: 0;
z-index: 2;
position: absolute;
top: 100px;
width: 250px;
}
./doc/qt/cpp/css/reset.css 0000644 0000156 0000165 00000001533 12701153654 015502 0 ustar jenkins jenkins /*
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.com/yui/license.html
version: 3.3.0
build: 3167
*/
html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;} ./doc/qt/cpp/css/qtquick.css 0000644 0000156 0000165 00000031751 12701153654 016046 0 ustar jenkins jenkins @media screen
{
/* basic elements */
html
{
color: #000000;
background: #FFFFFF;
}
table
{
border-collapse: collapse;
border-spacing: 0;
}
fieldset, img
{
border: 0;
max-width:100%;
}
address, caption, cite, code, dfn, em, strong, th, var, optgroup
{
font-style: inherit;
font-weight: inherit;
}
del, ins
{
text-decoration: none;
}
ol li
{
list-style: decimal;
}
ul li
{
list-style: none;
}
caption, th
{
text-align: left;
}
h1.title
{
font-weight: bold;
font-size: 150%;
}
h0
{
font-weight: bold;
font-size: 130%;
}
h1, h2, h3, h4, h5, h6
{
font-size: 100%;
}
q:before, q:after
{
content: '';
}
abbr, acronym
{
border: 0;
font-variant: normal;
}
sup, sub
{
vertical-align: baseline;
}
tt, .qmlreadonly span, .qmldefault span
{
word-spacing:0.5em;
}
legend
{
color: #000000;
}
strong
{
font-weight: bold;
}
em
{
font-style: italic;
}
body
{
margin: 0 1.5em 0 1.5em;
font-family: ubuntu;
line-height: normal
}
a
{
color: #00732F;
text-decoration: none;
}
hr
{
background-color: #E6E6E6;
border: 1px solid #E6E6E6;
height: 1px;
width: 100%;
text-align: left;
margin: 1.5em 0 1.5em 0;
}
pre
{
border: 1px solid #DDDDDD;
-moz-border-radius: 0.7em 0.7em 0.7em 0.7em;
-webkit-border-radius: 0.7em 0.7em 0.7em 0.7em;
border-radius: 0.7em 0.7em 0.7em 0.7em;
padding: 1em 1em 1em 1em;
overflow-x: auto;
}
table, pre
{
-moz-border-radius: 0.7em 0.7em 0.7em 0.7em;
-webkit-border-radius: 0.7em 0.7em 0.7em 0.7em;
border-radius: 0.7em 0.7em 0.7em 0.7em;
background-color: #F6F6F6;
border: 1px solid #E6E6E6;
border-collapse: separate;
margin-bottom: 2.5em;
}
pre {
font-size: 90%;
display: block;
overflow:hidden;
}
thead
{
margin-top: 0.5em;
font-weight: bold
}
th
{
padding: 0.5em 1.5em 0.5em 1em;
background-color: #E1E1E1;
border-left: 1px solid #E6E6E6;
}
td
{
padding: 0.25em 1.5em 0.25em 1em;
}
td.rightAlign
{
padding: 0.25em 0.5em 0.25em 1em;
}
table tr.odd
{
border-left: 1px solid #E6E6E6;
background-color: #F6F6F6;
color: black;
}
table tr.even
{
border-left: 1px solid #E6E6E6;
background-color: #ffffff;
color: #202020;
}
div.float-left
{
float: left; margin-right: 2em
}
div.float-right
{
float: right; margin-left: 2em
}
span.comment
{
color: #008B00;
}
span.string, span.char
{
color: #000084;
}
span.number
{
color: #a46200;
}
span.operator
{
color: #202020;
}
span.keyword
{
color: #840000;
}
span.name
{
color: black
}
span.type
{
font-weight: bold
}
span.type a:visited
{
color: #0F5300;
}
span.preprocessor
{
color: #404040
}
/* end basic elements */
/* font style elements */
.heading
{
font-weight: bold;
font-size: 125%;
}
.subtitle
{
font-size: 110%
}
.small-subtitle
{
font-size: 100%
}
.red
{
color:red;
}
/* end font style elements */
/* global settings*/
.header, .footer
{
display: block;
clear: both;
overflow: hidden;
}
/* end global settings*/
/* header elements */
.header .qtref
{
color: #00732F;
font-weight: bold;
font-size: 130%;
}
.header .content
{
margin-left: 5px;
margin-top: 5px;
margin-bottom: 0.5em;
}
.header .breadcrumb
{
font-size: 90%;
padding: 0.5em 0 0.5em 1em;
margin: 0;
background-color: #fafafa;
height: 1.35em;
border-bottom: 1px solid #d1d1d1;
}
.header .breadcrumb ul
{
margin: 0;
padding: 0;
}
.header .content
{
word-wrap: break-word;
}
.header .breadcrumb ul li
{
float: left;
background: url(../images/breadcrumb.png) no-repeat 0 3px;
padding-left: 1.5em;
margin-left: 1.5em;
}
.header .breadcrumb ul li.last
{
font-weight: normal;
}
.header .breadcrumb ul li a
{
color: #00732F;
}
.header .breadcrumb ul li.first
{
background-image: none;
padding-left: 0;
margin-left: 0;
}
.header .content ol li {
background: none;
margin-bottom: 1.0em;
margin-left: 1.2em;
padding-left: 0
}
.header .content li
{
background: url(../images/bullet_sq.png) no-repeat 0 5px;
margin-bottom: 1em;
padding-left: 1.2em;
}
/* end header elements */
/* content elements */
.content h1
{
font-weight: bold;
font-size: 130%
}
.content h2
{
font-weight: bold;
font-size: 120%;
width: 100%;
}
.content h3
{
font-weight: bold;
font-size: 110%;
width: 100%;
}
.content table p
{
margin: 0
}
.content ul
{
padding-left: 2.5em;
}
.content li
{
padding-top: 0.25em;
padding-bottom: 0.25em;
}
.content ul img {
vertical-align: middle;
}
.content a:visited
{
color: #4c0033;
text-decoration: none;
}
.content a:visited:hover
{
color: #4c0033;
text-decoration: underline;
}
a:hover
{
color: #4c0033;
text-decoration: underline;
}
descr p a
{
text-decoration: underline;
}
.descr p a:visited
{
text-decoration: underline;
}
.alphaChar{
width:95%;
background-color:#F6F6F6;
border:1px solid #E6E6E6;
-moz-border-radius: 7px 7px 7px 7px;
border-radius: 7px 7px 7px 7px;
-webkit-border-radius: 7px 7px 7px 7px;
font-size:12pt;
padding-left:10px;
margin-top:10px;
margin-bottom:10px;
}
.flowList{
/*vertical-align:top;*/
/*margin:20px auto;*/
column-count:3;
-webkit-column-count:3;
-moz-column-count:3;
/*
column-width:100%;
-webkit-column-width:200px;
-col-column-width:200px;
*/
column-gap:41px;
-webkit-column-gap:41px;
-moz-column-gap:41px;
column-rule: 1px dashed #ccc;
-webkit-column-rule: 1px dashed #ccc;
-moz-column-rule: 1px dashed #ccc;
}
.flowList dl{
}
.flowList dd{
/*display:inline-block;*/
margin-left:10px;
min-width:250px;
line-height: 1.5;
min-width:100%;
min-height:15px;
}
.flowList dd a{
}
.mainContent
{
padding-left:5px;
}
.content .flowList p{
padding:0px;
}
.content .alignedsummary
{
margin: 15px;
}
.qmltype
{
text-align: center;
font-size: 120%;
}
.qmlreadonly
{
padding-left: 5px;
float: right;
color: #254117;
}
.qmldefault
{
padding-left: 5px;
float: right;
color: red;
}
.qmldoc
{
}
.generic .alphaChar{
margin-top:5px;
}
.generic .odd .alphaChar{
background-color: #F6F6F6;
}
.generic .even .alphaChar{
background-color: #FFFFFF;
}
.memItemRight{
padding: 0.25em 1.5em 0.25em 0;
}
.highlightedCode
{
margin: 1.0em;
}
.annotated td {
padding: 0.25em 0.5em 0.25em 0.5em;
}
.toc
{
font-size: 80%
}
.header .content .toc ul
{
padding-left: 0px;
}
.content .toc h3 {
border-bottom: 0px;
margin-top: 0px;
}
.content .toc h3 a:hover {
color: #00732F;
text-decoration: none;
}
.content .toc .level2
{
margin-left: 1.5em;
}
.content .toc .level3
{
margin-left: 3.0em;
}
.content ul li
{
background: url(../images/bullet_sq.png) no-repeat 0 0.7em;
padding-left: 1em
}
.content .toc li
{
background: url(../images/bullet_dn.png) no-repeat 0 5px;
padding-left: 1em
}
.relpage
{
-moz-border-radius: 7px 7px 7px 7px;
-webkit-border-radius: 7px 7px 7px 7px;
border-radius: 7px 7px 7px 7px;
border: 1px solid #DDDDDD;
padding: 25px 25px;
clear: both;
}
.relpage ul
{
float: none;
padding: 1.5em;
}
h3.fn, span.fn
{
-moz-border-radius:7px 7px 7px 7px;
-webkit-border-radius:7px 7px 7px 7px;
border-radius:7px 7px 7px 7px;
background-color: #F6F6F6;
border-width: 1px;
border-style: solid;
border-color: #E6E6E6;
font-weight: bold;
word-spacing:3px;
padding:3px 5px;
}
.functionIndex {
font-size:12pt;
word-spacing:10px;
margin-bottom:10px;
background-color: #F6F6F6;
border-width: 1px;
border-style: solid;
border-color: #E6E6E6;
-moz-border-radius: 7px 7px 7px 7px;
-webkit-border-radius: 7px 7px 7px 7px;
border-radius: 7px 7px 7px 7px;
width:100%;
}
.centerAlign
{
text-align:center;
}
.rightAlign
{
text-align:right;
}
.leftAlign
{
text-align:left;
}
.topAlign{
vertical-align:top
}
.functionIndex a{
display:inline-block;
}
/* end content elements */
/* footer elements */
.footer
{
color: #393735;
font-size: 0.75em;
text-align: center;
padding-top: 1.5em;
padding-bottom: 1em;
background-color: #E6E7E8;
margin: 0;
}
.footer p
{
margin: 0.25em
}
.small
{
font-size: 0.5em;
}
/* end footer elements */
.item {
float: left;
position: relative;
width: 100%;
overflow: hidden;
}
.item .primary {
margin-right: 220px;
position: relative;
}
.item hr {
margin-left: -220px;
}
.item .secondary {
float: right;
width: 200px;
position: relative;
}
.item .cols {
clear: both;
display: block;
}
.item .cols .col {
float: left;
margin-left: 1.5%;
}
.item .cols .col.first {
margin-left: 0;
}
.item .cols.two .col {
width: 45%;
}
.item .box {
margin: 0 0 10px 0;
}
.item .box h3 {
margin: 0 0 10px 0;
}
.cols.unclear {
clear:none;
}
}
/* end of screen media */
/* start of print media */
@media print
{
input, textarea, .header, .footer, .toolbar, .feedback, .wrapper .hd, .wrapper .bd .sidebar, .wrapper .ft, #feedbackBox, #blurpage, .toc, .breadcrumb, .toolbar, .floatingResult
{
display: none;
background: none;
}
.content
{
background: none;
display: block;
width: 100%; margin: 0; float: none;
}
}
/* end of print media */
/* modify the TOC layouts */
div.toc ul {
padding-left: 20px;
}
div.toc li {
padding-left: 4px;
}
/* Remove the border around images*/
a img
{
border:none;
}
/*Add styling to the front pages*/
.threecolumn_area
{
padding-top: 20px;
padding-bottom: 20px;
}
.threecolumn_piece
{
display: inline-block;
margin-left: 78px;
margin-top: 8px;
padding: 0;
vertical-align: top;
width: 25.5%;
}
div.threecolumn_piece ul {
list-style-type: none;
padding-left: 0px;
margin-top: 2px;
}
div.threecolumn_piece p {
margin-bottom: 7px;
color: #5C626E;
text-decoration: none;
font-weight: bold;
}
div.threecolumn_piece li {
padding-left: 0px;
margin-bottom: 5px;
}
div.threecolumn_piece a {
font-weight: normal;
}
/* Add style to guide page*/
.fourcolumn_area
{
padding-top: 20px;
padding-bottom: 20px;
}
.fourcolumn_piece
{
display: inline-block;
margin-left: 35px;
margin-top: 8px;
padding: 0;
vertical-align: top;
width: 21.3%;
}
div.fourcolumn_piece ul {
list-style-type: none;
padding-left: 0px;
margin-top: 2px;
}
div.fourcolumn_piece p {
margin-bottom: 7px;
color: #40444D;
text-decoration: none;
font-weight: bold;
}
div.fourcolumn_piece li {
padding-left: 0px;
margin-bottom: 5px;
}
div.fourcolumn_piece a {
font-weight: normal;
}
./doc/qt/cpp/CMakeLists.txt 0000644 0000156 0000165 00000001210 12701153654 015606 0 ustar jenkins jenkins
add_subdirectory(examples)
include(UseDoxygen OPTIONAL)
add_doxygen(
qtdoc
PROJECT_NAME
"connectivity-api"
INPUT
"${CMAKE_SOURCE_DIR}/src/connectivity-api/connectivity-qt"
"${CMAKE_CURRENT_SOURCE_DIR}/pages"
EXAMPLE_PATH
"${CMAKE_SOURCE_DIR}/doc/qt/cpp/examples/"
STRIP_FROM_PATH
"${CMAKE_SOURCE_DIR}/src/connectivity-api/connectivity-qt"
STRIP_FROM_INC_PATH
"${CMAKE_SOURCE_DIR}/src/connectivity-api/connectivity-qt"
EXCLUDE_PATTERNS
*/internal/*
EXCLUDE_SYMBOLS
*::internal*
*::Priv
INSTALL
"${INSTALL_DOCDIR}/cpp"
XML
ALL
)
./doc/qt/cpp/pages/ 0000755 0000156 0000165 00000000000 12701153654 014153 5 ustar jenkins jenkins ./doc/qt/cpp/pages/mainpage.dox 0000644 0000156 0000165 00000001026 12701153654 016447 0 ustar jenkins jenkins /*!
\mainpage Ubuntu Connectivity API
\tableofcontents
\section sec_introduction Introduction
Ubuntu Connectivity API offers a way to access the connectivity related information of the system.
\section sec_general General Topics
- \ref using-cpp "Using this C++ API"
- \ref networking-status "Getting the networking status."
\section sec_bug_reports Reporting Bugs
If you find any problems with the or this documentation,
please file a bug in Connectivity API [Launchpad page](https://bugs.launchpad.net/connectivity-api).
*/
./doc/qt/cpp/pages/using.dox 0000644 0000156 0000165 00000001152 12701153654 016013 0 ustar jenkins jenkins /*!
\page using-cpp Using the C++ API
Install the development headers:
\code{.txt}
sudo apt-get install libconnectivity-qt1-dev
\endcode
Enable c++11 and use pkg-config to get the necessary compilation flags:
\code{.txt}
$ g++ myapp.cpp -std=c++11 `pkg-config --cflags --libs connectivity-qt1` -o myapp
\endcode
The headers can then be included as:
\code{.cpp}
// includes the ubuntu::connectivity::NetworkingStatus class
#include
\endcode
note:
Accessing the networking status from confined applications requires the connectivity policy group.
*/
./doc/qt/cpp/pages/networking-status.dox 0000644 0000156 0000165 00000002327 12701153654 020403 0 ustar jenkins jenkins /*!
\page networking-status Networking Status
Applications needing to access the overall system networking status must access the
ubuntu::connectivity::NetworkingStatus class. The class has properties
for the networking status and connection limitations of the system networking.
Accessing the networking status from confined applications requires
the connectivity policy group.
\section Setup
Manager is accessed by including the appropriate header:
\snippet example_networking_status.cpp include
and then creating an instance of the NetworkingStatus:
\snippet example_networking_status.cpp create networkingstatus
\section sec_networking_status Networking Status
\subsection sec_networking_status_status Status
The status of the system networking can be accessed through the ubuntu::connectivity::NetworkingStatus::status property:
\snippet example_networking_status.cpp status
\subsection sec_networking_status_limitations Limitations
The limitations can be accessed through the ubuntu::connectivity::NetworkingStatus::limitations property:
\snippet example_networking_status.cpp limitations
---
The complete example (found in examples/example_networking_status.cpp):
\include example_networking_status.cpp
*/
./doc/qt/cpp/examples/ 0000755 0000156 0000165 00000000000 12701153654 014672 5 ustar jenkins jenkins ./doc/qt/cpp/examples/example_networking_status.cpp 0000644 0000156 0000165 00000004637 12701153654 022715 0 ustar jenkins jenkins /*
* Copyright © 2014 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
* Authors:
* Antti Kaijanmäki
*/
#include
#include
#include
//! [include]
#include
using namespace connectivityqt;
//! [include]
static const QMap STATUS_MAP {
{Connectivity::Status::Offline, "Offline"},
{Connectivity::Status::Connecting, "Connecting"},
{Connectivity::Status::Online, "Online"},
};
int
main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
//! [create networkingstatus]
QScopedPointer ns(new Connectivity());
//! [create networkingstatus]
//! [status]
// normal getter
if (ns->status() == Connectivity::Status::Online)
{
qDebug() << "We are online.";
}
// Subscribe to system networking changes
QObject::connect(ns.data(),
&Connectivity::statusUpdated,
[](Connectivity::Status value)
{
qDebug() << "System networking status changed to: " + STATUS_MAP[value];
});
//! [status]
qDebug() << "System networking status: " + STATUS_MAP[ns->status()];
//! [limitations]
// normal getter
if (ns->limitations().isEmpty())
qDebug() << "No limitations";
// Subscribe to limitation changes
QObject::connect(ns.data(),
&Connectivity::limitationsUpdated,
[&ns](){
if (ns->limitations().isEmpty())
{
qDebug() << "No limitations.";
return;
}
qDebug() << "Limitations:";
if (ns->limitations().contains(Connectivity::Limitations::Bandwith))
{
qDebug() << " - Bandwith";
}
});
//! [limitations]
app.exec();
return 0;
}
./doc/qt/cpp/examples/CMakeLists.txt 0000644 0000156 0000165 00000000334 12701153654 017432 0 ustar jenkins jenkins
include_directories(${CMAKE_SOURCE_DIR}/src/connectivity-api/connectivity-qt)
add_executable(
networking_status
example_networking_status.cpp
)
target_link_libraries(networking_status ${CONNECTIVITY_QT_LIB_TARGET})
./doc/dbus/ 0000755 0000156 0000165 00000000000 12701153654 012603 5 ustar jenkins jenkins ./doc/dbus/connectivity-api.txt 0000644 0000156 0000165 00000001315 12701153654 016631 0 ustar jenkins jenkins Service com.ubuntu.connectivity1
Interface com.ubuntu.connectivity1.NetworkingStatus
Object path /com/ubuntu/connectivity1/NetworkingStatus
Policy group connectivity
Supports org.freedesktop.DBus.Introspectable
org.freedesktop.DBus.Properties
Properties array{string} Limitations [readonly]
String array representing the possible limitations
on networking.
Currently available limitations are:
"bandwith"
"bandwith" - indicates that the bandwith of the
Internet connection has limitations.
Applications should minimize their bandwith
usage if possible.
string Status [readonly]
Status of the Internet connectivity.
Possible values:
"offline", "connecting", "online"
./doc/CMakeLists.txt 0000644 0000156 0000165 00000000462 12701153654 014410 0 ustar jenkins jenkins set(INSTALL_DOCDIR ${CMAKE_INSTALL_DATAROOTDIR}/doc/connectivity-api)
option(BUILD_DOC "Build documentation by default" TRUE)
option(PRIVATE_DOCS "Build private documentation" FALSE)
add_subdirectory(qt)
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/dbus/
DESTINATION ${INSTALL_DOCDIR}/dbus/
)
./cmake/ 0000755 0000156 0000165 00000000000 12701153654 012161 5 ustar jenkins jenkins ./cmake/FindValgrind.cmake 0000644 0000156 0000165 00000001645 12701153654 015540 0 ustar jenkins jenkins
option(
ENABLE_MEMCHECK_OPTION
"If set to ON, enables automatic creation of memcheck targets"
OFF
)
find_program(
VALGRIND_PROGRAM
NAMES valgrind
)
if(VALGRIND_PROGRAM)
set(VALGRIND_PROGRAM_OPTIONS
"--suppressions=${CMAKE_SOURCE_DIR}/tests/data/valgrind.suppression"
"--error-exitcode=1"
"--leak-check=full"
"--gen-suppressions=all"
"--quiet"
)
endif()
find_package_handle_standard_args(
VALGRIND DEFAULT_MSG
VALGRIND_PROGRAM
)
function(add_valgrind_test)
foreach(_arg ${ARGN})
if ("VALGRIND" STREQUAL ${_arg})
if(ENABLE_MEMCHECK_OPTION AND VALGRIND_PROGRAM)
list(APPEND _vgargs ${VALGRIND_PROGRAM} ${VALGRIND_PROGRAM_OPTIONS})
endif()
else()
list(APPEND _vgargs ${_arg})
endif()
endforeach()
add_test(${_vgargs})
endfunction()
./cmake/COPYING-CMAKE-SCRIPTS 0000644 0000156 0000165 00000002457 12701153654 015167 0 ustar jenkins jenkins 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 copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
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.
./tests/ 0000755 0000156 0000165 00000000000 12701153654 012243 5 ustar jenkins jenkins ./tests/integration/ 0000755 0000156 0000165 00000000000 12701153654 014566 5 ustar jenkins jenkins ./tests/integration/indicator-network-test-base.cpp 0000644 0000156 0000165 00000054342 12701153654 022632 0 ustar jenkins jenkins /*
* Copyright (C) 2015 Canonical, Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
* Author: Pete Woods
*/
#include
#include
#include
#include
#include
using namespace QtDBusTest;
using namespace QtDBusMock;
using namespace std;
using namespace testing;
using namespace connectivityqt;
namespace mh = unity::gmenuharness;
IndicatorNetworkTestBase::IndicatorNetworkTestBase() :
dbusMock(dbusTestRunner)
{
DBusTypes::registerMetaTypes();
}
IndicatorNetworkTestBase::~IndicatorNetworkTestBase()
{
}
void IndicatorNetworkTestBase::SetUp()
{
if (qEnvironmentVariableIsSet("TEST_WITH_BUSTLE"))
{
const TestInfo* const test_info =
UnitTest::GetInstance()->current_test_info();
QDir::temp().mkpath("indicator-network-tests");
QDir testDir(QDir::temp().filePath("indicator-network-tests"));
dbusTestRunner.registerService(
DBusServicePtr(
new QProcessDBusService(
"", QDBusConnection::SessionBus,
"/usr/bin/bustle-pcap",
QStringList{"-e", testDir.filePath(QString("%1-%2").arg(test_info->name(), "session.log"))})));
dbusTestRunner.registerService(
DBusServicePtr(
new QProcessDBusService(
"", QDBusConnection::SystemBus,
"/usr/bin/bustle-pcap",
QStringList{"-y", testDir.filePath(QString("%1-%2").arg(test_info->name(), "system.log"))})));
}
dbusMock.registerNetworkManager();
dbusMock.registerNotificationDaemon();
// By default the ofono mock starts with one modem
dbusMock.registerOfono();
dbusMock.registerURfkill();
dbusMock.registerCustomMock(
DBusTypes::POWERD_DBUS_NAME,
DBusTypes::POWERD_DBUS_PATH,
DBusTypes::POWERD_DBUS_INTERFACE,
QDBusConnection::SystemBus);
dbusMock.registerCustomMock(
DBusTypes::WPASUPPLICANT_DBUS_NAME,
DBusTypes::WPASUPPLICANT_DBUS_PATH,
DBusTypes::WPASUPPLICANT_DBUS_INTERFACE,
QDBusConnection::SystemBus);
dbusMock.registerCustomMock(
"com.canonical.URLDispatcher",
"/com/canonical/URLDispatcher",
"com.canonical.URLDispatcher",
QDBusConnection::SessionBus);
dbusTestRunner.startServices();
// Set up a basic URL dispatcher mock
auto& urlDispatcher = dbusMock.mockInterface(
"com.canonical.URLDispatcher",
"/com/canonical/URLDispatcher",
"com.canonical.URLDispatcher",
QDBusConnection::SessionBus);
urlDispatcher.AddMethod(
"com.canonical.URLDispatcher",
"DispatchURL", "ss", "",
""
).waitForFinished();
urlDispatcher.AddMethod(
"com.canonical.URLDispatcher",
"TestURL", "as", "as",
"ret = args[0]"
).waitForFinished();
// Set up a basic WPA supplicant mock
auto& wpaSupplicant = dbusMock.mockInterface(
DBusTypes::WPASUPPLICANT_DBUS_NAME,
DBusTypes::WPASUPPLICANT_DBUS_PATH,
DBusTypes::WPASUPPLICANT_DBUS_INTERFACE,
QDBusConnection::SystemBus);
wpaSupplicant.AddMethod(
DBusTypes::WPASUPPLICANT_DBUS_INTERFACE,
"SetInterfaceFirmware",
"os",
"",
""
).waitForFinished();
// Set up a basic powerd mock - only supports power states
auto& powerd = dbusMock.mockInterface(
DBusTypes::POWERD_DBUS_NAME,
DBusTypes::POWERD_DBUS_PATH,
DBusTypes::POWERD_DBUS_INTERFACE,
QDBusConnection::SystemBus);
powerd.AddMethod(
DBusTypes::POWERD_DBUS_INTERFACE,
"requestSysState",
"si",
"s",
"ret = 'dummy_cookie'"
).waitForFinished();
powerd.AddMethod(
DBusTypes::POWERD_DBUS_INTERFACE,
"clearSysState",
"s",
"",
""
).waitForFinished();
// mock service creates ril_0 automatically
// Initial ConnectionManager properties are insane, fix them here
setConnectionManagerProperty(firstModem(), "Bearer", "none");
setConnectionManagerProperty(firstModem(), "Powered", false);
setConnectionManagerProperty(firstModem(), "Attached", false);
// Identify the test when looking at Bustle logs
QDBusConnection systemConnection = dbusTestRunner.systemConnection();
systemConnection.registerService("org.TestIndicatorNetworkService");
QDBusConnection sessionConnection = dbusTestRunner.sessionConnection();
sessionConnection.registerService("org.TestIndicatorNetworkService");
}
mh::MenuMatcher::Parameters IndicatorNetworkTestBase::phoneParameters()
{
return mh::MenuMatcher::Parameters(
"com.canonical.indicator.network",
{ { "indicator", "/com/canonical/indicator/network" } },
"/com/canonical/indicator/network/phone");
}
mh::MenuMatcher::Parameters IndicatorNetworkTestBase::unlockSimParameters(std::string const& busName, int exportId)
{
return mh::MenuMatcher::Parameters(
busName,
{ { "notifications", "/com/canonical/indicator/network/unlocksim" + to_string(exportId) } },
"/com/canonical/indicator/network/unlocksim" + to_string(exportId));
}
void IndicatorNetworkTestBase::startIndicator()
{
try
{
indicator.reset(
new QProcessDBusService(DBusTypes::DBUS_NAME,
QDBusConnection::SessionBus,
NETWORK_SERVICE_BIN,
QStringList()));
indicator->start(dbusTestRunner.sessionConnection());
}
catch (exception const& e)
{
cout << "startIndicator(): " << e.what() << endl;
throw;
}
}
QString IndicatorNetworkTestBase::createEthernetDevice(int state, const QString& id)
{
auto& networkManager(dbusMock.networkManagerInterface());
auto reply = networkManager.AddEthernetDevice(id, "eth" + id, state);
reply.waitForFinished();
if (reply.isError())
{
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
return reply;
}
QString IndicatorNetworkTestBase::createWiFiDevice(int state, const QString& id)
{
auto& networkManager(dbusMock.networkManagerInterface());
auto reply = networkManager.AddWiFiDevice(id, "wlan" + id, state);
reply.waitForFinished();
if (reply.isError())
{
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
return reply;
}
QString IndicatorNetworkTestBase::randomMac()
{
int high = 254;
int low = 1;
QString hardwareAddress;
bool first = true;
for (unsigned int i = 0; i < 6; ++i)
{
if (!first)
{
hardwareAddress.append(":");
}
int r = qrand() % ((high + 1) - low) + low;
hardwareAddress.append(QString("%1").arg(r, 2, 16, QChar('0')));
first = false;
}
return hardwareAddress;
}
void IndicatorNetworkTestBase::enableWiFi()
{
auto& urfkillInterface = dbusMock.urfkillInterface();
auto reply = urfkillInterface.Block(1, false);
reply.waitForFinished();
if (reply.isError())
{
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
}
void IndicatorNetworkTestBase::disableWiFi()
{
auto& urfkillInterface = dbusMock.urfkillInterface();
auto reply = urfkillInterface.Block(1, true);
reply.waitForFinished();
if (reply.isError())
{
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
}
QString IndicatorNetworkTestBase::createAccessPoint(const QString& id, const QString& ssid, const QString& device, uchar strength,
Secure secure, ApMode apMode, const QString& mac)
{
int secflags(NM_802_11_AP_SEC_NONE);
if (secure == Secure::insecure)
{
secflags = NM_802_11_AP_SEC_NONE;
}
else if (secure == Secure::wpa)
{
secflags = NM_802_11_AP_SEC_KEY_MGMT_PSK;
}
else if (secure == Secure::wpa_enterprise)
{
secflags = NM_802_11_AP_SEC_KEY_MGMT_802_1X;
}
auto& networkManager(dbusMock.networkManagerInterface());
auto reply = networkManager.AddAccessPoint(
device, id, ssid,
mac,
apMode == ApMode::adhoc ? NM_802_11_MODE_ADHOC : NM_802_11_MODE_INFRA,
0, 0, strength,
secflags);
reply.waitForFinished();
if (reply.isError())
{
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
return reply;
}
void IndicatorNetworkTestBase::removeAccessPoint(const QString& device, const QString& ap)
{
auto& nm = dbusMock.networkManagerInterface();
auto reply = nm.RemoveAccessPoint(device, ap);
reply.waitForFinished();
if (reply.isError())
{
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
}
QString IndicatorNetworkTestBase::createAccessPointConnection(const QString& id, const QString& ssid, const QString& device)
{
auto& networkManager(dbusMock.networkManagerInterface());
auto reply = networkManager.AddWiFiConnection(device, id, ssid,
"");
reply.waitForFinished();
if (reply.isError())
{
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
return reply;
}
void IndicatorNetworkTestBase::removeWifiConnection(const QString& device, const QString& connection)
{
auto& nm = dbusMock.networkManagerInterface();
auto reply = nm.RemoveWifiConnection(device, connection);
reply.waitForFinished();
if (reply.isError())
{
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
}
QString IndicatorNetworkTestBase::createActiveConnection(const QString& id, const QString& device, const QString& connection, const QString& specificObject)
{
auto& nm = dbusMock.networkManagerInterface();
auto reply = nm.AddActiveConnection(QStringList() << device,
connection,
specificObject,
id,
NM_ACTIVE_CONNECTION_STATE_ACTIVATED);
reply.waitForFinished();
if (reply.isError())
{
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
return reply;
}
void IndicatorNetworkTestBase::removeActiveConnection(const QString& device, const QString& active_connection)
{
auto& nm = dbusMock.networkManagerInterface();
auto reply = nm.RemoveActiveConnection(device, active_connection);
reply.waitForFinished();
if (reply.isError())
{
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
}
void IndicatorNetworkTestBase::setGlobalConnectedState(int state)
{
auto& nm = dbusMock.networkManagerInterface();
auto reply = nm.SetGlobalConnectionState(state);
reply.waitForFinished();
if (reply.isError())
{
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
}
void IndicatorNetworkTestBase::setNmProperty(const QString& path, const QString& iface, const QString& name, const QVariant& value)
{
auto& nm = dbusMock.networkManagerInterface();
auto reply = nm.SetProperty(path, iface, name, QDBusVariant(value));
reply.waitForFinished();
if (reply.isError())
{
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
}
QString IndicatorNetworkTestBase::createModem(const QString& id)
{
auto& ofono(dbusMock.ofonoInterface());
QVariantMap modemProperties {{ "Powered", false } };
auto reply = ofono.AddModem(id, modemProperties);
reply.waitForFinished();
if (reply.isError()) {
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
return "";
}
QString path = reply.value();
// Initial ConnectionManager properties are insane, fix them here
setConnectionManagerProperty(path, "Bearer", "none");
setConnectionManagerProperty(path, "Powered", false);
setConnectionManagerProperty(path, "Attached", false);
return path;
}
void IndicatorNetworkTestBase::setModemProperty(const QString& path, const QString& propertyName, const QVariant& value)
{
auto& ofono(dbusMock.ofonoModemInterface(path));
auto reply = ofono.SetProperty(propertyName, QDBusVariant(value));
reply.waitForFinished();
if (reply.isError()) {
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
}
void IndicatorNetworkTestBase::setSimManagerProperty(const QString& path, const QString& propertyName, const QVariant& value)
{
auto& ofono(dbusMock.ofonoSimManagerInterface(path));
auto reply = ofono.SetProperty(propertyName, QDBusVariant(value));
reply.waitForFinished();
if (reply.isError()) {
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
}
void IndicatorNetworkTestBase::setConnectionManagerProperty(const QString& path, const QString& propertyName, const QVariant& value)
{
auto& ofono(dbusMock.ofonoConnectionManagerInterface(path));
auto reply = ofono.SetProperty(propertyName, QDBusVariant(value));
reply.waitForFinished();
if (reply.isError()) {
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
}
void IndicatorNetworkTestBase::setNetworkRegistrationProperty(const QString& path, const QString& propertyName, const QVariant& value)
{
auto& ofono(dbusMock.ofonoNetworkRegistrationInterface(path));
auto reply = ofono.SetProperty(propertyName, QDBusVariant(value));
reply.waitForFinished();
if (reply.isError()) {
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
}
OrgFreedesktopDBusMockInterface& IndicatorNetworkTestBase::notificationsMockInterface()
{
return dbusMock.mockInterface("org.freedesktop.Notifications",
"/org/freedesktop/Notifications",
"org.freedesktop.Notifications",
QDBusConnection::SessionBus);
}
OrgFreedesktopDBusMockInterface& IndicatorNetworkTestBase::modemMockInterface(const QString& path)
{
return dbusMock.mockInterface("org.ofono",
path,
"",
QDBusConnection::SystemBus);
}
OrgFreedesktopDBusMockInterface& IndicatorNetworkTestBase::networkManagerMockInterface()
{
return dbusMock.mockInterface(NM_DBUS_SERVICE,
NM_DBUS_PATH,
NM_DBUS_INTERFACE,
QDBusConnection::SystemBus);
}
bool IndicatorNetworkTestBase::qDBusArgumentToMap(QVariant const& variant, QVariantMap& map)
{
if (variant.canConvert())
{
QDBusArgument value(variant.value());
if (value.currentType() == QDBusArgument::MapType)
{
value >> map;
return true;
}
}
return false;
}
QString IndicatorNetworkTestBase::firstModem()
{
return "/ril_0";
}
mh::MenuItemMatcher IndicatorNetworkTestBase::flightModeSwitch(bool toggled)
{
return mh::MenuItemMatcher::checkbox()
.label("Flight Mode")
.action("indicator.airplane.enabled")
.toggled(toggled);
}
mh::MenuItemMatcher IndicatorNetworkTestBase::accessPoint(const string& ssid, Secure secure,
ApMode apMode, ConnectionStatus connectionStatus, uchar strength)
{
return mh::MenuItemMatcher::checkbox()
.label(ssid)
.widget("unity.widgets.systemsettings.tablet.accesspoint")
.toggled(connectionStatus == ConnectionStatus::connected)
.pass_through_attribute(
"x-canonical-wifi-ap-strength-action",
shared_ptr(g_variant_new_byte(strength), &mh::gvariant_deleter))
.boolean_attribute("x-canonical-wifi-ap-is-secure", secure != Secure::insecure)
.boolean_attribute("x-canonical-wifi-ap-is-enterprise", secure == Secure::wpa_enterprise)
.boolean_attribute("x-canonical-wifi-ap-is-adhoc", apMode == ApMode::adhoc);
}
mh::MenuItemMatcher IndicatorNetworkTestBase::wifiEnableSwitch(bool toggled)
{
return mh::MenuItemMatcher::checkbox()
.label("Wi-Fi")
.action("indicator.wifi.enable") // This action is accessed by system-settings-ui, do not change it
.toggled(toggled);
}
mh::MenuItemMatcher IndicatorNetworkTestBase::wifiSettings()
{
return mh::MenuItemMatcher()
.label("Wi-Fi settings…")
.action("indicator.wifi.settings");
}
mh::MenuItemMatcher IndicatorNetworkTestBase::modemInfo(const string& simIdentifier,
const string& label,
const string& statusIcon,
bool locked,
const string& connectivityIcon)
{
return mh::MenuItemMatcher()
.widget("com.canonical.indicator.network.modeminfoitem")
.pass_through_string_attribute("x-canonical-modem-sim-identifier-label-action", simIdentifier)
.pass_through_string_attribute("x-canonical-modem-connectivity-icon-action", connectivityIcon)
.pass_through_string_attribute("x-canonical-modem-status-label-action", label)
.pass_through_string_attribute("x-canonical-modem-status-icon-action", statusIcon)
.pass_through_boolean_attribute("x-canonical-modem-roaming-action", false)
.pass_through_boolean_attribute("x-canonical-modem-locked-action", locked);
}
mh::MenuItemMatcher IndicatorNetworkTestBase::cellularSettings()
{
return mh::MenuItemMatcher()
.label("Cellular settings…")
.action("indicator.cellular.settings");
}
QString IndicatorNetworkTestBase::createVpnConnection(const QString& id,
const QString& serviceType,
const QStringMap& data,
const QStringMap& secrets)
{
OrgFreedesktopNetworkManagerSettingsInterface settingsInterface(
NM_DBUS_SERVICE, NM_DBUS_PATH_SETTINGS,
dbusTestRunner.systemConnection());
QVariantDictMap connection;
connection["connection"] = QVariantMap {
{"timestamp", 1441979296},
{"type", "vpn"},
{"id", id},
{"uuid", QUuid::createUuid().toString().mid(1,36)}
};
connection["vpn"] = QVariantMap {
{"service-type", serviceType},
{"data", QVariant::fromValue(data)}
};
if (!secrets.isEmpty())
{
connection["vpn"]["secrets"] = QVariant::fromValue(secrets);
}
connection["ipv4"] = QVariantMap {
{"routes", QStringList()},
{"never-default", true},
{"addresses", QStringList()},
{"dns", QStringList()},
{"method", "auto"}
};
connection["ipv6"] = QVariantMap {
{"addresses", QStringList()},
{"ip6-privacy", 0},
{"dns", QStringList()},
{"never-default", true},
{"routes", QStringList()},
{"method", "auto"}
};
auto reply = settingsInterface.AddConnection(connection);
reply.waitForFinished();
if (reply.isError())
{
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
QDBusObjectPath path(reply);
return path.path();
}
void IndicatorNetworkTestBase::deleteSettings(const QString& path)
{
OrgFreedesktopNetworkManagerSettingsConnectionInterface iface(NM_DBUS_SERVICE, path,
dbusTestRunner.systemConnection());
auto reply = iface.Delete();
reply.waitForFinished();
if (reply.isError())
{
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
}
Connectivity::UPtr IndicatorNetworkTestBase::newConnectivity()
{
Connectivity::registerMetaTypes();
auto connectivity = make_unique(dbusTestRunner.sessionConnection());
if (!connectivity->isInitialized())
{
QSignalSpy initSpy(connectivity.get(), SIGNAL(initialized()));
initSpy.wait();
}
return connectivity;
}
QVariantList IndicatorNetworkTestBase::getMethodCall(const QSignalSpy& spy, const QString& method)
{
for(const auto& call: spy)
{
if (call.first().toString() == method)
{
return call.at(1).toList();
}
}
throw domain_error(qPrintable("No method call [" + method + "] could be found"));
}
mh::MenuItemMatcher IndicatorNetworkTestBase::vpnSettings()
{
return mh::MenuItemMatcher()
.label("VPN settings…")
.action("indicator.vpn.settings");
}
mh::MenuItemMatcher IndicatorNetworkTestBase::vpnConnection(const string& name, ConnectionStatus connected)
{
return mh::MenuItemMatcher::checkbox()
.label(name)
.themed_icon("icon", {"network-vpn"})
.toggled(connected == ConnectionStatus::connected);
}
./tests/integration/test-connectivity-api.cpp 0000644 0000156 0000165 00000062300 12701153654 021535 0 ustar jenkins jenkins
/*
* Copyright (C) 2015 Canonical, Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
* Author: Pete Woods
*/
#include
#include
#include
#include
#include
using namespace std;
using namespace testing;
using namespace connectivityqt;
namespace
{
class TestConnectivityApi: public IndicatorNetworkTestBase
{
protected:
static void SetUpTestCase()
{
Connectivity::registerMetaTypes();
}
};
TEST_F(TestConnectivityApi, OnlineStatus)
{
// Set up disconnected
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// Start the indicator
ASSERT_NO_THROW(startIndicator());
// Connect to the service
auto connectivity(newConnectivity());
QSignalSpy spy(connectivity.get(), &Connectivity::statusUpdated);
// Check we are connected
EXPECT_EQ(Connectivity::Status::Offline, connectivity->status());
// Now we are connecting
spy.clear();
setGlobalConnectedState(NM_STATE_CONNECTING);
WAIT_FOR_SIGNALS(spy, 1);
EXPECT_EQ(Connectivity::Status::Connecting, connectivity->status());
// Now we are connecting
spy.clear();
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
WAIT_FOR_SIGNALS(spy, 1);
EXPECT_EQ(Connectivity::Status::Online, connectivity->status());
}
TEST_F(TestConnectivityApi, FollowsFlightMode)
{
// Set up disconnected with flight mode on
setGlobalConnectedState(NM_STATE_DISCONNECTED);
ASSERT_TRUE(dbusMock.urfkillInterface().FlightMode(true));
// Start the indicator
ASSERT_NO_THROW(startIndicator());
// Connect to the service
auto connectivity(newConnectivity());
// Check flight mode is enabled
EXPECT_TRUE(connectivity->flightMode());
// Now disable flight mode
ASSERT_TRUE(dbusMock.urfkillInterface().FlightMode(false));
// Check that flight mode gets updated
{
QSignalSpy spy(connectivity.get(), SIGNAL(flightModeUpdated(bool)));
ASSERT_TRUE(spy.wait());
ASSERT_EQ(1, spy.size());
}
// Check that flight mode is disabled
EXPECT_FALSE(connectivity->flightMode());
}
TEST_F(TestConnectivityApi, FlightModeTalksToURfkill)
{
// Start the indicator
ASSERT_NO_THROW(startIndicator());
// Connect to the UrfKill mock
auto& urfkillInterface = dbusMock.urfkillInterface();
QSignalSpy urfkillSpy(&urfkillInterface, SIGNAL(FlightModeChanged(bool)));
// Connect the the service
auto connectivity(newConnectivity());
// Follow the flightMode property
QSignalSpy flightModeSpy(connectivity.get(), SIGNAL(flightModeUpdated(bool)));
// Follow the switch enabled properties
QSignalSpy flightModeSwitchSpy(connectivity.get(), SIGNAL(flightModeSwitchEnabledUpdated(bool)));
QSignalSpy wifiSwitchSpy(connectivity.get(), SIGNAL(wifiSwitchEnabledUpdated(bool)));
QSignalSpy hotspotSwitchSpy(connectivity.get(), SIGNAL(hotspotSwitchEnabledUpdated(bool)));
// Check that nothing is happening yet
EXPECT_TRUE(connectivity->flightModeSwitchEnabled());
EXPECT_TRUE(connectivity->wifiSwitchEnabled());
EXPECT_TRUE(connectivity->hotspotSwitchEnabled());
// Enable flight mode
connectivity->setFlightMode(true);
// We should first get the switch disabled change
WAIT_FOR_SIGNALS(flightModeSwitchSpy, 1);
EXPECT_EQ(flightModeSwitchSpy.first(), QVariantList() << QVariant(false));
if (wifiSwitchSpy.size() != 1)
{
ASSERT_TRUE(wifiSwitchSpy.wait());
}
ASSERT_EQ(1, wifiSwitchSpy.size());
EXPECT_EQ(wifiSwitchSpy.first(), QVariantList() << QVariant(false));
if (hotspotSwitchSpy.size() != 1)
{
ASSERT_TRUE(hotspotSwitchSpy.wait());
}
ASSERT_EQ(1, hotspotSwitchSpy.size());
EXPECT_EQ(hotspotSwitchSpy.first(), QVariantList() << QVariant(false));
// Wait to be notified that flight mode was enabled
if (urfkillSpy.size() != 1)
{
ASSERT_TRUE(urfkillSpy.wait());
}
ASSERT_EQ(1, urfkillSpy.size());
EXPECT_EQ(urfkillSpy.first(), QVariantList() << QVariant(true));
// The switch enabled change should complete
if (flightModeSwitchSpy.size() != 2)
{
ASSERT_TRUE(flightModeSwitchSpy.wait());
}
ASSERT_EQ(2, flightModeSwitchSpy.size());
EXPECT_EQ(flightModeSwitchSpy.last(), QVariantList() << QVariant(true));
if (wifiSwitchSpy.size() != 2)
{
ASSERT_TRUE(wifiSwitchSpy.wait());
}
ASSERT_EQ(2, wifiSwitchSpy.size());
EXPECT_EQ(wifiSwitchSpy.last(), QVariantList() << QVariant(true));
// Wait for flight mode property change
if (flightModeSpy.size() != 1)
{
ASSERT_TRUE(flightModeSpy.wait());
}
ASSERT_EQ(1, flightModeSpy.size());
EXPECT_EQ(flightModeSpy.first(), QVariantList() << QVariant(true));
// Check that nothing is happening again
EXPECT_TRUE(connectivity->flightModeSwitchEnabled());
EXPECT_TRUE(connectivity->wifiSwitchEnabled());
// Hotspot not available when in flight mode
EXPECT_FALSE(connectivity->hotspotSwitchEnabled());
// The icing on the cake
EXPECT_TRUE(connectivity->flightMode());
// Start again
urfkillSpy.clear();
flightModeSwitchSpy.clear();
wifiSwitchSpy.clear();
hotspotSwitchSpy.clear();
flightModeSpy.clear();
// Disable flight mode
connectivity->setFlightMode(false);
// We should first get the unstoppable operation change
ASSERT_TRUE(flightModeSwitchSpy.wait());
ASSERT_EQ(1, flightModeSwitchSpy.size());
EXPECT_EQ(flightModeSwitchSpy.first(), QVariantList() << QVariant(false));
if (wifiSwitchSpy.size() != 1)
{
ASSERT_TRUE(wifiSwitchSpy.wait());
}
ASSERT_EQ(1, wifiSwitchSpy.size());
EXPECT_EQ(wifiSwitchSpy.first(), QVariantList() << QVariant(false));
// Wait to be notified that flight mode was disabled
if (urfkillSpy.size() != 1)
{
ASSERT_TRUE(urfkillSpy.wait());
}
ASSERT_EQ(1, urfkillSpy.size());
EXPECT_EQ(urfkillSpy.first(), QVariantList() << QVariant(false));
// The toggles should become enabled again
if (flightModeSwitchSpy.size() != 2)
{
ASSERT_TRUE(flightModeSwitchSpy.wait());
}
ASSERT_EQ(2, flightModeSwitchSpy.size());
EXPECT_EQ(wifiSwitchSpy.last(), QVariantList() << QVariant(true));
if (wifiSwitchSpy.size() != 2)
{
ASSERT_TRUE(wifiSwitchSpy.wait());
}
ASSERT_EQ(2, wifiSwitchSpy.size());
EXPECT_EQ(wifiSwitchSpy.last(), QVariantList() << QVariant(true));
if (hotspotSwitchSpy.size() != 1)
{
ASSERT_TRUE(hotspotSwitchSpy.wait());
}
ASSERT_EQ(1, hotspotSwitchSpy.size());
EXPECT_EQ(hotspotSwitchSpy.first(), QVariantList() << QVariant(true));
// Wait for flight mode property change
if (flightModeSpy.size() != 1)
{
ASSERT_TRUE(flightModeSpy.wait());
}
ASSERT_EQ(1, flightModeSpy.size());
EXPECT_EQ(flightModeSpy.first(), QVariantList() << QVariant(false));
// Check that nothing is happening again
EXPECT_TRUE(connectivity->flightModeSwitchEnabled());
EXPECT_TRUE(connectivity->wifiSwitchEnabled());
EXPECT_TRUE(connectivity->hotspotSwitchEnabled());
// The icing on the cake
EXPECT_FALSE(connectivity->flightMode());
}
TEST_F(TestConnectivityApi, WifiToggleTalksToUrfkill)
{
// Start the indicator
ASSERT_NO_THROW(startIndicator());
// Connect to the UrfKill mock
OrgFreedesktopURfkillKillswitchInterface wifiKillswitchInterface(
DBusTypes::URFKILL_BUS_NAME, DBusTypes::URFKILL_WIFI_OBJ_PATH,
dbusTestRunner.systemConnection());
QSignalSpy urfkillSpy(&wifiKillswitchInterface, SIGNAL(StateChanged()));
// Connect the the service
auto connectivity(newConnectivity());
// Follow the wifiEnabled property
QSignalSpy wifiEnabledSpy(connectivity.get(), SIGNAL(wifiEnabledUpdated(bool)));
// Follow the switch enabled properties
QSignalSpy flightModeSwitchSpy(connectivity.get(), SIGNAL(flightModeSwitchEnabledUpdated(bool)));
QSignalSpy wifiSwitchSpy(connectivity.get(), SIGNAL(wifiSwitchEnabledUpdated(bool)));
QSignalSpy hotspotSwitchSpy(connectivity.get(), SIGNAL(hotspotSwitchEnabledUpdated(bool)));
// Check that nothing is happening yet
EXPECT_TRUE(connectivity->flightModeSwitchEnabled());
EXPECT_TRUE(connectivity->wifiSwitchEnabled());
EXPECT_TRUE(connectivity->hotspotSwitchEnabled());
EXPECT_TRUE(connectivity->wifiEnabled());
EXPECT_EQ(0, wifiKillswitchInterface.state());
// Disable WiFi
connectivity->setwifiEnabled(false);
// Check the switch enabled flags change
ASSERT_TRUE(flightModeSwitchSpy.wait());
ASSERT_EQ(1, flightModeSwitchSpy.size());
EXPECT_EQ(flightModeSwitchSpy.first(), QVariantList() << QVariant(false));
if (wifiSwitchSpy.size() != 1)
{
ASSERT_TRUE(wifiSwitchSpy.wait());
}
ASSERT_EQ(1, wifiSwitchSpy.size());
EXPECT_EQ(wifiSwitchSpy.first(), QVariantList() << QVariant(false));
if (hotspotSwitchSpy.size() != 1)
{
ASSERT_TRUE(hotspotSwitchSpy.wait());
}
ASSERT_EQ(1, hotspotSwitchSpy.size());
EXPECT_EQ(hotspotSwitchSpy.first(), QVariantList() << QVariant(false));
// Wait to be notified that wifi was toggled
if (urfkillSpy.size() != 1)
{
ASSERT_TRUE(urfkillSpy.wait());
}
ASSERT_EQ(1, urfkillSpy.size());
// Switch should be re-enabled now
if (flightModeSwitchSpy.size() != 2)
{
ASSERT_TRUE(flightModeSwitchSpy.wait());
}
ASSERT_EQ(2, flightModeSwitchSpy.size());
EXPECT_EQ(flightModeSwitchSpy.last(), QVariantList() << QVariant(true));
if (hotspotSwitchSpy.size() != 2)
{
ASSERT_TRUE(hotspotSwitchSpy.wait());
}
ASSERT_EQ(2, hotspotSwitchSpy.size());
EXPECT_EQ(hotspotSwitchSpy.last(), QVariantList() << QVariant(true));
if (wifiSwitchSpy.size() != 2)
{
ASSERT_TRUE(wifiSwitchSpy.wait());
}
ASSERT_EQ(2, wifiSwitchSpy.size());
EXPECT_EQ(wifiSwitchSpy.last(), QVariantList() << QVariant(true));
// Wait for wifi enabled property change
if (wifiEnabledSpy.size() != 1)
{
ASSERT_TRUE(wifiEnabledSpy.wait());
}
ASSERT_EQ(1, wifiEnabledSpy.size());
EXPECT_EQ(wifiEnabledSpy.first(), QVariantList() << QVariant(false));
// Check switches are enabled
EXPECT_TRUE(connectivity->flightModeSwitchEnabled());
EXPECT_TRUE(connectivity->wifiSwitchEnabled());
EXPECT_TRUE(connectivity->hotspotSwitchEnabled());
// The icing on the cake
EXPECT_FALSE(connectivity->wifiEnabled());
EXPECT_EQ(1, wifiKillswitchInterface.state());
// Start again
urfkillSpy.clear();
flightModeSwitchSpy.clear();
wifiSwitchSpy.clear();
hotspotSwitchSpy.clear();
wifiEnabledSpy.clear();
// Enable wifi
connectivity->setwifiEnabled(true);
// Toggles should be disabled
ASSERT_TRUE(flightModeSwitchSpy.wait());
ASSERT_EQ(1, flightModeSwitchSpy.size());
EXPECT_EQ(flightModeSwitchSpy.first(), QVariantList() << QVariant(false));
if (wifiSwitchSpy.size() != 1)
{
ASSERT_TRUE(wifiSwitchSpy.wait());
}
ASSERT_EQ(1, wifiSwitchSpy.size());
EXPECT_EQ(wifiSwitchSpy.first(), QVariantList() << QVariant(false));
if (hotspotSwitchSpy.size() != 1)
{
ASSERT_TRUE(hotspotSwitchSpy.wait());
}
ASSERT_EQ(1, hotspotSwitchSpy.size());
EXPECT_EQ(hotspotSwitchSpy.first(), QVariantList() << QVariant(false));
// Wait to be notified that wifi was toggled
if (urfkillSpy.size() != 1)
{
ASSERT_TRUE(urfkillSpy.wait());
}
ASSERT_EQ(1, urfkillSpy.size());
// Toggles should be re-enabled
if (flightModeSwitchSpy.size() != 2)
{
ASSERT_TRUE(flightModeSwitchSpy.wait());
}
ASSERT_EQ(2, flightModeSwitchSpy.size());
EXPECT_EQ(wifiSwitchSpy.last(), QVariantList() << QVariant(true));
if (wifiSwitchSpy.size() != 2)
{
ASSERT_TRUE(wifiSwitchSpy.wait());
}
ASSERT_EQ(2, wifiSwitchSpy.size());
EXPECT_EQ(wifiSwitchSpy.last(), QVariantList() << QVariant(true));
// Hotspot should become available again
if (hotspotSwitchSpy.size() != 2)
{
ASSERT_TRUE(hotspotSwitchSpy.wait());
}
ASSERT_EQ(2, hotspotSwitchSpy.size());
EXPECT_EQ(hotspotSwitchSpy.last(), QVariantList() << QVariant(true));
// Wait for wifi enabled property change
if (wifiEnabledSpy.size() != 1)
{
ASSERT_TRUE(wifiEnabledSpy.wait());
}
ASSERT_EQ(1, wifiEnabledSpy.size());
EXPECT_EQ(wifiEnabledSpy.first(), QVariantList() << QVariant(true));
// All toggles should be enabled
EXPECT_TRUE(connectivity->flightModeSwitchEnabled());
EXPECT_TRUE(connectivity->wifiSwitchEnabled());
EXPECT_TRUE(connectivity->hotspotSwitchEnabled());
// The icing on the cake
EXPECT_TRUE(connectivity->wifiEnabled());
EXPECT_EQ(0, wifiKillswitchInterface.state());
}
TEST_F(TestConnectivityApi, Status)
{
// Start the indicator
ASSERT_NO_THROW(startIndicator());
// Connect the the service
auto connectivity(newConnectivity());
// Check we are online
EXPECT_TRUE(connectivity->online());
EXPECT_EQ(Connectivity::Status::Online, connectivity->status());
// Listen to property changes
QSignalSpy onlineSpy(connectivity.get(), SIGNAL(onlineUpdated(bool)));
QSignalSpy statusSpy(connectivity.get(), SIGNAL(statusUpdated(connectivityqt::Connectivity::Status)));
// Set up disconnected with flight mode on
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// Wait for changes
ASSERT_TRUE(onlineSpy.wait());
if (statusSpy.isEmpty())
{
ASSERT_TRUE(statusSpy.wait());
}
// Check we are online
EXPECT_FALSE(connectivity->online());
EXPECT_EQ(Connectivity::Status::Offline, connectivity->status());
// Check we have just one signal
ASSERT_EQ(1, onlineSpy.size());
ASSERT_EQ(1, statusSpy.size());
EXPECT_EQ(QVariantList() << QVariant(false), onlineSpy.first());
EXPECT_EQ(Connectivity::Status::Offline, qvariant_cast(statusSpy.first().first()));
}
TEST_F(TestConnectivityApi, Limitations)
{
// Start the indicator
ASSERT_NO_THROW(startIndicator());
// Connect the the service
auto connectivity(newConnectivity());
// These methods will always return these values - i.e. are not implemented
EXPECT_EQ(QVector(), connectivity->limitations());
EXPECT_FALSE(connectivity->limitedBandwith());
}
TEST_F(TestConnectivityApi, HotspotConfig)
{
setGlobalConnectedState(NM_STATE_DISCONNECTED);
auto device = createWiFiDevice(NM_DEVICE_STATE_DISCONNECTED);
// Start the indicator
ASSERT_NO_THROW(startIndicator());
auto& powerdMock = dbusMock.mockInterface(DBusTypes::POWERD_DBUS_NAME,
DBusTypes::POWERD_DBUS_PATH,
DBusTypes::POWERD_DBUS_INTERFACE,
QDBusConnection::SystemBus);
QSignalSpy powerdMockCallSpy(
&powerdMock,
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
auto& nmMock = dbusMock.mockInterface(NM_DBUS_SERVICE,
NM_DBUS_PATH,
NM_DBUS_INTERFACE,
QDBusConnection::SystemBus);
QSignalSpy nmMockCallSpy(
&nmMock,
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
auto& nmSettingsMock = dbusMock.mockInterface(NM_DBUS_SERVICE,
NM_DBUS_PATH_SETTINGS,
NM_DBUS_IFACE_SETTINGS,
QDBusConnection::SystemBus);
QSignalSpy nmSettingsMockCallSpy(
&nmSettingsMock,
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
OrgFreedesktopNetworkManagerSettingsInterface settings(
NM_DBUS_SERVICE, NM_DBUS_PATH_SETTINGS, dbusTestRunner.systemConnection());
QSignalSpy settingsNewConnectionSpy(
&settings,
SIGNAL(NewConnection(const QDBusObjectPath &)));
// Connect the the service
auto connectivity(newConnectivity());
QSignalSpy storedSpy(connectivity.get(), SIGNAL(hotspotStoredUpdated(bool)));
QSignalSpy enabledSpy(connectivity.get(), SIGNAL(hotspotEnabledUpdated(bool)));
QSignalSpy passwordSpy(connectivity.get(), SIGNAL(hotspotPasswordUpdated(const QString&)));
EXPECT_EQ("Ubuntu", connectivity->hotspotSsid().toStdString());
EXPECT_EQ("wpa-psk", connectivity->hotspotAuth().toStdString());
EXPECT_FALSE(connectivity->hotspotStored());
EXPECT_FALSE(connectivity->hotspotEnabled());
connectivity->setHotspotPassword("the password");
if (passwordSpy.empty())
{
ASSERT_TRUE(passwordSpy.wait());
}
EXPECT_FALSE(passwordSpy.empty());
EXPECT_EQ("the password", connectivity->hotspotPassword().toStdString());
connectivity->setHotspotEnabled(true);
if (enabledSpy.empty())
{
ASSERT_TRUE(enabledSpy.wait());
}
EXPECT_FALSE(enabledSpy.empty());
if (storedSpy.empty())
{
ASSERT_TRUE(storedSpy.wait());
}
EXPECT_FALSE(storedSpy.empty());
if (powerdMockCallSpy.empty())
{
ASSERT_TRUE(powerdMockCallSpy.wait());
}
EXPECT_FALSE(powerdMockCallSpy.empty());
if (nmSettingsMockCallSpy.empty())
{
ASSERT_TRUE(nmSettingsMockCallSpy.wait());
}
EXPECT_FALSE(nmSettingsMockCallSpy.empty());
if (settingsNewConnectionSpy.empty())
{
ASSERT_TRUE(settingsNewConnectionSpy.wait());
}
EXPECT_FALSE(settingsNewConnectionSpy.empty());
EXPECT_TRUE(connectivity->hotspotEnabled());
EXPECT_TRUE(connectivity->hotspotStored());
// Connect to method calls on the newly added connection
auto connectionPath = qvariant_cast(settingsNewConnectionSpy.first().first());
auto& connectionSettingsMock = dbusMock.mockInterface(NM_DBUS_SERVICE, connectionPath.path(),
NM_DBUS_IFACE_SETTINGS_CONNECTION,
QDBusConnection::SystemBus);
QSignalSpy connectionSettingsMockCallSpy(
&connectionSettingsMock,
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
// Expect a wakelock request
EXPECT_EQ(
QVariantList({"connectivity-service", int(1)}),
getMethodCall(powerdMockCallSpy, "requestSysState"));
{
auto call = getMethodCall(nmSettingsMockCallSpy, "AddConnection");
// Decode the QDBusArgument
QVariantDictMap connection;
qvariant_cast(call.first()) >> connection;
EXPECT_EQ(QVariantMap({
{"mode", "ap"},
{"security", "802-11-wireless-security"},
{"ssid", "Ubuntu"}
}), connection["802-11-wireless"]);
EXPECT_EQ(QVariantMap({
{"group", "ccmp"},
{"key-mgmt", "wpa-psk"},
{"pairwise" , QStringList{"ccmp"}},
{"proto" , QStringList{"rsn"}},
{"psk", "the password"}
}), connection["802-11-wireless-security"]);
EXPECT_FALSE(connection["connection"]["autoconnect"].toBool());
}
// Next we'll disable the hotspot
storedSpy.clear();
enabledSpy.clear();
passwordSpy.clear();
powerdMockCallSpy.clear();
nmMockCallSpy.clear();
nmSettingsMockCallSpy.clear();
connectivity->setHotspotEnabled(false);
if (powerdMockCallSpy.empty())
{
ASSERT_TRUE(powerdMockCallSpy.wait());
}
EXPECT_FALSE(powerdMockCallSpy.empty());
if (nmMockCallSpy.empty())
{
ASSERT_TRUE(nmMockCallSpy.wait());
}
EXPECT_FALSE(nmMockCallSpy.empty());
if (enabledSpy.empty())
{
ASSERT_TRUE(enabledSpy.wait());
}
EXPECT_FALSE(enabledSpy.empty());
EXPECT_FALSE(connectivity->hotspotEnabled());
EXPECT_TRUE(connectivity->hotspotStored());
// Expect a wakelock cancel
EXPECT_EQ(
QVariantList{"dummy_cookie"},
getMethodCall(powerdMockCallSpy, "clearSysState"));
// We should expect a disconnect call
{
auto call = getMethodCall(nmMockCallSpy, "DeactivateConnection");
EXPECT_EQ("/org/freedesktop/NetworkManager/ActiveConnection/0", qvariant_cast(call.first()).path());
}
}
TEST_F(TestConnectivityApi, InsecureHotspotConfig)
{
setGlobalConnectedState(NM_STATE_DISCONNECTED);
auto device = createWiFiDevice(NM_DEVICE_STATE_DISCONNECTED);
// Start the indicator
ASSERT_NO_THROW(startIndicator());
auto& nmSettingsMock = dbusMock.mockInterface(NM_DBUS_SERVICE,
NM_DBUS_PATH_SETTINGS,
NM_DBUS_IFACE_SETTINGS,
QDBusConnection::SystemBus);
QSignalSpy nmSettingsMockCallSpy(
&nmSettingsMock,
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
OrgFreedesktopNetworkManagerSettingsInterface settings(
NM_DBUS_SERVICE, NM_DBUS_PATH_SETTINGS, dbusTestRunner.systemConnection());
QSignalSpy settingsNewConnectionSpy(
&settings,
SIGNAL(NewConnection(const QDBusObjectPath &)));
// Connect the the service
auto connectivity(newConnectivity());
QSignalSpy storedSpy(connectivity.get(), SIGNAL(hotspotStoredUpdated(bool)));
QSignalSpy enabledSpy(connectivity.get(), SIGNAL(hotspotEnabledUpdated(bool)));
QSignalSpy authSpy(connectivity.get(), SIGNAL(hotspotAuthUpdated(const QString&)));
EXPECT_EQ("Ubuntu", connectivity->hotspotSsid().toStdString());
EXPECT_EQ("wpa-psk", connectivity->hotspotAuth().toStdString());
EXPECT_FALSE(connectivity->hotspotStored());
EXPECT_FALSE(connectivity->hotspotEnabled());
connectivity->setHotspotAuth("none");
if (authSpy.empty())
{
ASSERT_TRUE(authSpy.wait());
}
EXPECT_FALSE(authSpy.empty());
EXPECT_EQ("none", connectivity->hotspotAuth().toStdString());
connectivity->setHotspotEnabled(true);
if (enabledSpy.empty())
{
ASSERT_TRUE(enabledSpy.wait());
}
EXPECT_FALSE(enabledSpy.empty());
if (storedSpy.empty())
{
ASSERT_TRUE(storedSpy.wait());
}
EXPECT_FALSE(storedSpy.empty());
if (nmSettingsMockCallSpy.empty())
{
ASSERT_TRUE(nmSettingsMockCallSpy.wait());
}
EXPECT_FALSE(nmSettingsMockCallSpy.empty());
if (settingsNewConnectionSpy.empty())
{
ASSERT_TRUE(settingsNewConnectionSpy.wait());
}
EXPECT_FALSE(settingsNewConnectionSpy.empty());
EXPECT_TRUE(connectivity->hotspotEnabled());
EXPECT_TRUE(connectivity->hotspotStored());
// Connect to method calls on the newly added connection
auto connectionPath = qvariant_cast(settingsNewConnectionSpy.first().first());
auto& connectionSettingsMock = dbusMock.mockInterface(NM_DBUS_SERVICE, connectionPath.path(),
NM_DBUS_IFACE_SETTINGS_CONNECTION,
QDBusConnection::SystemBus);
QSignalSpy connectionSettingsMockCallSpy(
&connectionSettingsMock,
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
{
auto call = getMethodCall(nmSettingsMockCallSpy, "AddConnection");
// Decode the QDBusArgument
QVariantDictMap connection;
qvariant_cast(call.first()) >> connection;
EXPECT_EQ(QVariantMap({
{"mode", "ap"},
{"ssid", "Ubuntu"}
}), connection["802-11-wireless"]);
EXPECT_EQ(QVariantMap(), connection["802-11-wireless-security"]);
EXPECT_FALSE(connection["connection"]["autoconnect"].toBool());
}
}
TEST_F(TestConnectivityApi, HotspotModemAvailable)
{
setGlobalConnectedState(NM_STATE_DISCONNECTED);
auto device = createWiFiDevice(NM_DEVICE_STATE_DISCONNECTED);
// Start the indicator
ASSERT_NO_THROW(startIndicator());
auto& nmSettingsMock = dbusMock.mockInterface(NM_DBUS_SERVICE,
NM_DBUS_PATH_SETTINGS,
NM_DBUS_IFACE_SETTINGS,
QDBusConnection::SystemBus);
QSignalSpy nmSettingsMockCallSpy(
&nmSettingsMock,
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
OrgFreedesktopNetworkManagerSettingsInterface settings(
NM_DBUS_SERVICE, NM_DBUS_PATH_SETTINGS, dbusTestRunner.systemConnection());
QSignalSpy settingsNewConnectionSpy(
&settings,
SIGNAL(NewConnection(const QDBusObjectPath &)));
// Connect the the service
auto connectivity(newConnectivity());
EXPECT_TRUE(connectivity->modemAvailable());
}
}
./tests/integration/indicator-network-test-base.h 0000644 0000156 0000165 00000016250 12701153654 022273 0 ustar jenkins jenkins /*
* Copyright (C) 2015 Canonical, Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
* Author: Pete Woods
*/
#pragma once
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
inline QString qVariantToString(const QVariant& variant) {
QString output;
QDebug dbg(&output);
dbg << variant;
return output;
}
inline void PrintTo(const QVariant& variant, std::ostream* os) {
QString output;
QDebug dbg(&output);
dbg << variant;
*os << "QVariant(" << output.toStdString() << ")";
}
inline void PrintTo(const QString& s, std::ostream* os) {
*os << "\"" << s.toStdString() << "\"";
}
inline void PrintTo(const QStringList& list, std::ostream* os) {
QString output;
QDebug dbg(&output);
dbg << list;
*os << "QStringList(" << output.toStdString() << ")";
}
inline void PrintTo(const QList& list, std::ostream* os) {
QString output;
for (const auto& path: list)
{
output.append("\"" + path.path() + "\",");
}
*os << "QList(" << output.toStdString() << ")";
}
#define WAIT_FOR_SIGNALS(signalSpy, signalsExpected)\
{\
while (signalSpy.size() < signalsExpected)\
{\
ASSERT_TRUE(signalSpy.wait());\
}\
ASSERT_EQ(signalsExpected, signalSpy.size());\
}
#define CHECK_METHOD_CALL(signalSpy, signalIndex, methodName, ...)\
{\
QVariantList const& call(signalSpy.at(signalIndex));\
EXPECT_EQ(methodName, call.at(0));\
auto arguments = vector>{__VA_ARGS__};\
if (!arguments.empty())\
{\
QVariantList const& args(call.at(1).toList());\
ASSERT_LE(arguments.back().first + 1, args.size());\
for (auto const& argument : arguments)\
{\
EXPECT_EQ(argument.second, args.at(argument.first));\
}\
}\
}
class IndicatorNetworkTestBase: public testing::Test
{
public:
enum class Secure
{
insecure,
wpa,
wpa_enterprise
};
enum class ApMode
{
infra,
adhoc
};
enum class ConnectionStatus
{
connected,
disconnected
};
IndicatorNetworkTestBase();
~IndicatorNetworkTestBase();
protected:
void SetUp() override;
static unity::gmenuharness::MenuMatcher::Parameters phoneParameters();
static unity::gmenuharness::MenuMatcher::Parameters unlockSimParameters(std::string const& busName, int exportId);
void startIndicator();
QString createEthernetDevice(int state, const QString& id = "0");
QString createWiFiDevice(int state, const QString& id = "0");
static QString randomMac();
void enableWiFi();
void disableWiFi();
QString createAccessPoint(const QString& id, const QString& ssid, const QString& device, uchar strength = 100,
Secure secure = Secure::wpa, ApMode apMode = ApMode::infra, const QString& mac = randomMac());
void removeAccessPoint(const QString& device, const QString& ap);
QString createAccessPointConnection(const QString& id, const QString& ssid, const QString& device);
void removeWifiConnection(const QString& device, const QString& connection);
QString createActiveConnection(const QString& id, const QString& device, const QString& connection, const QString& specificObject);
void removeActiveConnection(const QString& device, const QString& active_connection);
void setGlobalConnectedState(int state);
void setNmProperty(const QString& path, const QString& iface, const QString& name, const QVariant& value);
QString createModem(const QString& id);
void setModemProperty(const QString& path, const QString& propertyName, const QVariant& value);
void setSimManagerProperty(const QString& path, const QString& propertyName, const QVariant& value);
void setConnectionManagerProperty(const QString& path, const QString& propertyName, const QVariant& value);
void setNetworkRegistrationProperty(const QString& path, const QString& propertyName, const QVariant& value);
OrgFreedesktopDBusMockInterface& notificationsMockInterface();
OrgFreedesktopDBusMockInterface& modemMockInterface(const QString& path);
OrgFreedesktopDBusMockInterface& networkManagerMockInterface();
QString createVpnConnection(const QString& id,
const QString& serviceType = "org.freedesktop.NetworkManager.openvpn",
const QStringMap& =
{
{"connection-type", "tls"},
{"remote", "remote"},
{"ca", "/path/to/ca.crt"},
{"cert", "/path/to/cert.crt"},
{"cert-pass-flags", "1"},
{"key", "/path/to/key.key"}
},
const QStringMap& secrets = {});
void deleteSettings(const QString& path);
connectivityqt::Connectivity::UPtr newConnectivity();
QVariantList getMethodCall(const QSignalSpy& spy, const QString& method);
static bool qDBusArgumentToMap(QVariant const& variant, QVariantMap& map);
static QString firstModem();
static unity::gmenuharness::MenuItemMatcher flightModeSwitch(bool toggled = false);
static unity::gmenuharness::MenuItemMatcher accessPoint(const std::string& ssid, Secure secure,
ApMode apMode, ConnectionStatus connectionStatus, uchar strength = 100);
static unity::gmenuharness::MenuItemMatcher wifiEnableSwitch(bool toggled = true);
static unity::gmenuharness::MenuItemMatcher wifiSettings();
static unity::gmenuharness::MenuItemMatcher modemInfo(const std::string& simIdentifier,
const std::string& label,
const std::string& statusIcon,
bool locked = false,
const std::string& connectivityIcon = "");
static unity::gmenuharness::MenuItemMatcher cellularSettings();
static unity::gmenuharness::MenuItemMatcher vpnSettings();
static unity::gmenuharness::MenuItemMatcher vpnConnection(const std::string& name, ConnectionStatus connected = ConnectionStatus::disconnected);
QtDBusTest::DBusTestRunner dbusTestRunner;
QtDBusMock::DBusMock dbusMock;
QtDBusTest::DBusServicePtr indicator;
};
./tests/integration/test-indicator.cpp 0000644 0000156 0000165 00000422114 12701153654 020227 0 ustar jenkins jenkins /*
* Copyright (C) 2015 Canonical, Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
* Author: Pete Woods
*/
#include
#include
#include
#include
using namespace std;
using namespace testing;
namespace mh = unity::gmenuharness;
namespace
{
class TestIndicator: public IndicatorNetworkTestBase
{
};
TEST_F(TestIndicator, BasicMenuContents)
{
setGlobalConnectedState(NM_STATE_DISCONNECTED);
ASSERT_NO_THROW(startIndicator());
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.action("indicator.phone.network-status")
.state_icons({"gsm-3g-full", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::all)
.submenu()
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.section()
.item(modemInfo("", "fake.tel", "gsm-3g-full"))
.item(cellularSettings())
)
.item(wifiEnableSwitch())
.item(wifiSettings())
.item(mh::MenuItemMatcher()
.section()
)
).match());
}
TEST_F(TestIndicator, OneDisconnectedAccessPointAtStartup)
{
setGlobalConnectedState(NM_STATE_DISCONNECTED);
auto device = createWiFiDevice(NM_DEVICE_STATE_DISCONNECTED);
auto ap = createAccessPoint("0", "the ssid", device);
auto connection = createAccessPointConnection("0", "the ssid", device);
ASSERT_NO_THROW(startIndicator());
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-full", "nm-no-connection"})
.submenu()
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()) // <-- modems are under here
.item(wifiEnableSwitch())
.item(mh::MenuItemMatcher()
.section()
.item(accessPoint("the ssid",
Secure::wpa,
ApMode::infra,
ConnectionStatus::disconnected)
)
)
.item(wifiSettings())
.item(mh::MenuItemMatcher()
.section()
)
).match());
}
TEST_F(TestIndicator, OneConnectedAccessPointAtStartup)
{
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
auto ap = createAccessPoint("0", "the ssid", device);
auto connection = createAccessPointConnection("0", "the ssid", device);
createActiveConnection("0", device, connection, ap);
ASSERT_NO_THROW(startIndicator());
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-full", "nm-signal-100-secure"})
.submenu()
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()) // <-- modems are under here
.item(wifiEnableSwitch())
.item(mh::MenuItemMatcher()
.section()
.item(accessPoint("the ssid",
Secure::wpa,
ApMode::infra,
ConnectionStatus::connected)
)
)
.item(wifiSettings())
.item(mh::MenuItemMatcher()
.section()
)
).match());
}
TEST_F(TestIndicator, AddOneDisconnectedAccessPointAfterStartup)
{
setGlobalConnectedState(NM_STATE_DISCONNECTED);
auto device = createWiFiDevice(NM_DEVICE_STATE_DISCONNECTED);
ASSERT_NO_THROW(startIndicator());
auto ap = createAccessPoint("0", "the ssid", device);
auto connection = createAccessPointConnection("0", "the ssid", device);
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.submenu()
.item(flightModeSwitch())
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch())
.item(mh::MenuItemMatcher()
.section()
.item(accessPoint("the ssid",
Secure::wpa,
ApMode::infra,
ConnectionStatus::disconnected)
)
)
.item(wifiSettings())
.item(mh::MenuItemMatcher()
.section()
)
).match());
}
TEST_F(TestIndicator, AddOneConnectedAccessPointAfterStartup)
{
setGlobalConnectedState(NM_STATE_DISCONNECTED);
auto device = createWiFiDevice(NM_DEVICE_STATE_DISCONNECTED);
ASSERT_NO_THROW(startIndicator());
auto ap = createAccessPoint("0", "the ssid", device);
auto connection = createAccessPointConnection("0", "the ssid", device);
createActiveConnection("0", device, connection, ap);
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.submenu()
.item(flightModeSwitch())
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch())
.item(mh::MenuItemMatcher()
.section()
.item(accessPoint("the ssid",
Secure::wpa,
ApMode::infra,
ConnectionStatus::connected)
)
)
.item(wifiSettings())
.item(mh::MenuItemMatcher()
.section()
)
).match());
}
TEST_F(TestIndicator, SecondModem)
{
createModem("ril_1"); // ril_0 already exists
ASSERT_NO_THROW(startIndicator());
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.submenu()
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.section()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-full"))
.item(modemInfo("SIM 2", "fake.tel", "gsm-3g-full"))
.item(cellularSettings())
)
.item(wifiEnableSwitch())
.item(wifiSettings())
.item(mh::MenuItemMatcher()
.section()
)
).match());
}
TEST_F(TestIndicator, FlightModeTalksToURfkill)
{
ASSERT_NO_THROW(startIndicator());
auto& urfkillInterface = dbusMock.urfkillInterface();
QSignalSpy urfkillSpy(&urfkillInterface, SIGNAL(FlightModeChanged(bool)));
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.submenu()
.item(flightModeSwitch(false)
.activate() // <--- Activate the action now
)
).match());
// Wait to be notified that flight mode was enabled
WAIT_FOR_SIGNALS(urfkillSpy, 1);
EXPECT_EQ(urfkillSpy.first(), QVariantList() << QVariant(true));
}
TEST_F(TestIndicator, IndicatorListensToURfkill)
{
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
auto ap = createAccessPoint("0", "the ssid", device);
auto connection = createAccessPointConnection("0", "the ssid", device);
createActiveConnection("0", device, connection, ap);
ASSERT_NO_THROW(startIndicator());
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch())
.item(mh::MenuItemMatcher()
.has_exactly(1) // <-- has one access point
)
).match());
ASSERT_TRUE(dbusMock.urfkillInterface().FlightMode(true));
removeWifiConnection(device, connection);
removeAccessPoint(device, ap);
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(true))
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch(false))
.item(mh::MenuItemMatcher()
.is_empty() // <-- no access points
)
).match());
}
TEST_F(TestIndicator, SimStates_NoSIM)
{
// set flight mode off, wifi off, and cell data off
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// set no sim
setSimManagerProperty(firstModem(), "Present", false);
// start the indicator
ASSERT_NO_THROW(startIndicator());
// check indicator is just a 0-bar wifi icon
// check sim status shows “No SIM” with crossed sim card icon
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("", "No SIM", "no-simcard"))
.item(cellularSettings())
)
).match());
}
TEST_F(TestIndicator, SimStates_NoSIM2)
{
// set flight mode off, wifi off, and cell data off
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// set no sim 2
auto modem1 = createModem("ril_1");
setSimManagerProperty(modem1, "Present", false);
// start the indicator
ASSERT_NO_THROW(startIndicator());
// check indicator is a 4-bar signal icon and a 0-bar wifi icon
// check sim 2 status shows “No SIM” with crossed sim card icon
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-full", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-full"))
.item(modemInfo("SIM 2", "No SIM", "no-simcard"))
.item(cellularSettings())
)
).match());
}
TEST_F(TestIndicator, SimStates_LockedSIM)
{
// set flight mode off, wifi off, and cell data off, and sim in
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// set sim locked
setSimManagerProperty(firstModem(), "PinRequired", "pin");
// start the indicator
ASSERT_NO_THROW(startIndicator());
// check indicator is a locked sim card and a 0-bar wifi icon.
// check sim status shows “SIM Locked”, with locked sim card icon and a “Unlock SIM” button beneath.
// check that the “Unlock SIM” button has the correct action name.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"simcard-locked", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("", "SIM Locked", "simcard-locked", true)
.string_attribute("x-canonical-modem-locked-action", "indicator.modem.1::locked")
)
.item(cellularSettings())
)
).match());
// set sim unlocked
setSimManagerProperty(firstModem(), "PinRequired", "none");
// check indicator is a 4-bar signal icon and a 0-bar wifi icon
// check sim status shows correct carrier name with 4-bar signal icon.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-full", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("", "fake.tel", "gsm-3g-full"))
.item(cellularSettings())
)
).match());
}
TEST_F(TestIndicator, SimStates_LockedSIM2)
{
// set flight mode off, wifi off, and cell data off, and sim in
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// set sim 2 locked
auto modem1 = createModem("ril_1");
setSimManagerProperty(modem1, "PinRequired", "pin");
// start the indicator
ASSERT_NO_THROW(startIndicator());
// check indicator is a 4-bar signal icon, a locked sim card and a 0-bar wifi icon.
// check sim 2 status shows “SIM Locked”, with locked sim card icon and a “Unlock SIM” button beneath.
// check that the “Unlock SIM” button has the correct action name.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-full", "simcard-locked", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-full"))
.item(modemInfo("SIM 2", "SIM Locked", "simcard-locked", true))
.item(cellularSettings())
)
).match());
// set sim 2 unlocked
setSimManagerProperty(modem1, "PinRequired", "none");
// check indicator is 4-bar signal icon, a 4-bar signal icon and a 0-bar wifi icon
// check sim statuses show correct carrier names with 4-bar signal icons.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-full", "gsm-3g-full", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-full"))
.item(modemInfo("SIM 2", "fake.tel", "gsm-3g-full"))
.item(cellularSettings())
)
).match());
}
TEST_F(TestIndicator, SimStates_UnlockedSIM)
{
// set flight mode off, wifi off, cell data off, sim in, and sim unlocked
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// set no signal
setNetworkRegistrationProperty(firstModem(), "Strength", QVariant::fromValue(uchar(0)));
// start the indicator
ASSERT_NO_THROW(startIndicator());
// check indicator is a crossed signal icon and a 0-bar wifi icon.
// check sim status shows “No Signal” with crossed signal icon.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-no-service", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("", "No Signal", "gsm-3g-no-service"))
.item(cellularSettings())
)
).match());
// set sim searching
setNetworkRegistrationProperty(firstModem(), "Status", "searching");
// check indicator is a disabled signal icon and a 0-bar wifi icon.
// check sim status shows “Searching” with disabled signal icon.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-disabled", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("", "Searching", "gsm-3g-disabled"))
.item(cellularSettings())
)
).match());
// set sim registered
setNetworkRegistrationProperty(firstModem(), "Status", "registered");
// set signal strength to 1
setNetworkRegistrationProperty(firstModem(), "Strength", QVariant::fromValue(uchar(1)));
// check indicator is a 0-bar signal icon and a 0-bar wifi icon.
// check sim status shows correct carrier name with 0-bar signal icon.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-none", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("", "fake.tel", "gsm-3g-none"))
.item(cellularSettings())
)
).match());
// set signal strength to 6
setNetworkRegistrationProperty(firstModem(), "Strength", QVariant::fromValue(uchar(6)));
// check indicator is a 1-bar signal icon and a 0-bar wifi icon.
// check sim status shows correct carrier name with 1-bar signal icon.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-low", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("", "fake.tel", "gsm-3g-low"))
.item(cellularSettings())
)
).match());
// set signal strength to 16
setNetworkRegistrationProperty(firstModem(), "Strength", QVariant::fromValue(uchar(16)));
// check indicator is a 2-bar signal icon and a 0-bar wifi icon.
// check sim status shows correct carrier name with 2-bar signal icon.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-medium", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("", "fake.tel", "gsm-3g-medium"))
.item(cellularSettings())
)
).match());
// set signal strength to 26
setNetworkRegistrationProperty(firstModem(), "Strength", QVariant::fromValue(uchar(26)));
// check indicator is a 3-bar signal icon and a 0-bar wifi icon.
// check sim status shows correct carrier name with 3-bar signal icon.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-high", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("", "fake.tel", "gsm-3g-high"))
.item(cellularSettings())
)
).match());
// set signal strength to 39
setNetworkRegistrationProperty(firstModem(), "Strength", QVariant::fromValue(uchar(39)));
// check indicator is a 4-bar signal icon and a 0-bar wifi icon.
// check sim status shows correct carrier name with 4-bar signal icon.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-full", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("", "fake.tel", "gsm-3g-full"))
.item(cellularSettings())
)
).match());
}
TEST_F(TestIndicator, SimStates_UnlockedSIM2)
{
// set flight mode off, wifi off, cell data off, sim in, and sim unlocked
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// set no signal on sim 2
auto modem1 = createModem("ril_1");
setNetworkRegistrationProperty(modem1, "Strength", QVariant::fromValue(uchar(0)));
// start the indicator
ASSERT_NO_THROW(startIndicator());
// check indicator is a 4-bar signal icon, a crossed signal icon and a 0-bar wifi icon.
// check sim 2 status shows “No Signal” with crossed signal icon.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-full", "gsm-3g-no-service", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-full"))
.item(modemInfo("SIM 2", "No Signal", "gsm-3g-no-service"))
.item(cellularSettings())
)
).match());
// set sim searching
setNetworkRegistrationProperty(modem1, "Status", "searching");
// check indicator is a 4-bar signal icon, a disabled signal icon and a 0-bar wifi icon.
// check sim 2 status shows “Searching” with disabled signal icon.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-full", "gsm-3g-disabled", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-full"))
.item(modemInfo("SIM 2", "Searching", "gsm-3g-disabled"))
.item(cellularSettings())
)
).match());
// set sim registered
setNetworkRegistrationProperty(modem1, "Status", "registered");
// set signal strength to 1
setNetworkRegistrationProperty(modem1, "Strength", QVariant::fromValue(uchar(1)));
// check indicator is a 4-bar signal icon, a 0-bar signal icon and a 0-bar wifi icon.
// check sim 2 status shows correct carrier name with 0-bar signal icon.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-full", "gsm-3g-none", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-full"))
.item(modemInfo("SIM 2", "fake.tel", "gsm-3g-none"))
.item(cellularSettings())
)
).match());
// set signal strength to 6
setNetworkRegistrationProperty(modem1, "Strength", QVariant::fromValue(uchar(6)));
// check indicator is a 4-bar signal icon, a 1-bar signal icon and a 0-bar wifi icon.
// check sim 2 status shows correct carrier name with 1-bar signal icon.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-full", "gsm-3g-low", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-full"))
.item(modemInfo("SIM 2", "fake.tel", "gsm-3g-low"))
.item(cellularSettings())
)
).match());
// set signal strength to 16
setNetworkRegistrationProperty(modem1, "Strength", QVariant::fromValue(uchar(16)));
// check indicator is a 4-bar signal icon, a 2-bar signal icon and a 0-bar wifi icon.
// check sim 2 status shows correct carrier name with 2-bar signal icon.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-full", "gsm-3g-medium", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-full"))
.item(modemInfo("SIM 2", "fake.tel", "gsm-3g-medium"))
.item(cellularSettings())
)
).match());
// set signal strength to 26
setNetworkRegistrationProperty(modem1, "Strength", QVariant::fromValue(uchar(26)));
// check indicator is a 4-bar signal icon, a 3-bar signal icon and a 0-bar wifi icon.
// check sim 2 status shows correct carrier name with 3-bar signal icon.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-full", "gsm-3g-high", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-full"))
.item(modemInfo("SIM 2", "fake.tel", "gsm-3g-high"))
.item(cellularSettings())
)
).match());
// set signal strength to 39
setNetworkRegistrationProperty(modem1, "Strength", QVariant::fromValue(uchar(39)));
// check indicator is a 4-bar signal icon, a 4-bar signal icon and a 0-bar wifi icon.
// check sim 2 status shows correct carrier name with 4-bar signal icon.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-full", "gsm-3g-full", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-full"))
.item(modemInfo("SIM 2", "fake.tel", "gsm-3g-full"))
.item(cellularSettings())
)
).match());
}
TEST_F(TestIndicator, FlightMode_NoSIM)
{
// set wifi on, flight mode off
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// add and connect to 2-bar unsecure AP
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
auto ap = createAccessPoint("0", "the ssid", device, 40, Secure::insecure);
auto connection = createAccessPointConnection("0", "the ssid", device);
auto activeConnection = createActiveConnection("0", device, connection, ap);
// start the indicator
ASSERT_NO_THROW(startIndicator());
// set no sim
setSimManagerProperty(firstModem(), "Present", false);
// check indicator is just a 2-bar wifi icon
// check sim status shows “No SIM” with crossed sim card icon.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-signal-50"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "No SIM", "no-simcard"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.section()
.item(accessPoint("the ssid",
Secure::insecure,
ApMode::infra,
ConnectionStatus::connected,
40)
)
)
).match());
// set flight mode on
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false)
.activate()
)
).match());
// Disconnect
setGlobalConnectedState(NM_STATE_DISCONNECTED);
removeActiveConnection(device, activeConnection);
removeWifiConnection(device, connection);
removeAccessPoint(device, ap);
// check that the wifi switch turns off
// check indicator is a plane icon and a 0-bar wifi icon
// check sim status shows “No SIM” with crossed sim card icon (unchanged).
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"airplane-mode", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(true))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "No SIM", "no-simcard"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(false))
.item(mh::MenuItemMatcher()
.is_empty()
)
).match());
// set flight mode off
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(true)
.activate()
)
).match());
// And we're back
ap = createAccessPoint("1", "the ssid", device, 40, Secure::insecure);
connection = createAccessPointConnection("1", "the ssid", device);
activeConnection = createActiveConnection("1", device, connection, ap);
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// check that the wifi switch turns back on
// check indicator is just a 2-bar wifi icon
// check sim status shows “No SIM” with crossed sim card icon.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-signal-50"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "No SIM", "no-simcard"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(true))
).match());
}
TEST_F(TestIndicator, FlightMode_LockedSIM)
{
// set wifi on, flight mode off
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// add and connect to 1-bar secure AP
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
auto ap = createAccessPoint("0", "the ssid", device, 20, Secure::wpa);
auto connection = createAccessPointConnection("0", "the ssid", device);
auto activeConnection = createActiveConnection("0", device, connection, ap);
// start the indicator
ASSERT_NO_THROW(startIndicator());
// set sim locked
setSimManagerProperty(firstModem(), "PinRequired", "pin");
// check indicator is a locked sim card and a 1-bar locked wifi icon
// check sim status shows “SIM Locked”, with locked sim card icon and a “Unlock SIM” button beneath.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"simcard-locked", "nm-signal-25-secure"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "SIM Locked", "simcard-locked", true))
.item(cellularSettings())
)
.item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.section()
.item(accessPoint("the ssid",
Secure::wpa,
ApMode::infra,
ConnectionStatus::connected,
20)
)
)
).match());
// set flight mode on
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false)
.activate()
)
).match());
// Disconnect
removeActiveConnection(device, activeConnection);
removeWifiConnection(device, connection);
removeAccessPoint(device, ap);
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// check that the wifi switch turns off
// check indicator is a plane icon, a locked sim card and a 0-bar wifi icon
// check sim status shows “SIM Locked”, with locked sim card icon and a “Unlock SIM” button beneath (unchanged).
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"airplane-mode", "simcard-locked", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(true))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "SIM Locked", "simcard-locked", true))
.item(cellularSettings())
)
.item(wifiEnableSwitch(false))
.item(mh::MenuItemMatcher()
.is_empty()
)
).match());
// set flight mode off
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(true)
.activate()
)
).match());
// And we're back
ap = createAccessPoint("1", "the ssid", device, 20, Secure::wpa);
connection = createAccessPointConnection("1", "the ssid", device);
activeConnection = createActiveConnection("1", device, connection, ap);
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// check that the wifi switch turns back on
// check indicator is a locked sim card and a 1-bar locked wifi icon
// check sim status shows “SIM Locked”, with locked sim card icon and a “Unlock SIM” button beneath.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"simcard-locked", "nm-signal-25-secure"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "SIM Locked", "simcard-locked", true))
.item(cellularSettings())
)
.item(wifiEnableSwitch(true))
).match());
}
TEST_F(TestIndicator, FlightMode_WifiOff)
{
// set wifi on, flight mode off
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// add some APs (secure / unsecure / adhoc / varied strength)
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
auto ap1 = createAccessPoint("1", "NSD", device, 0, Secure::wpa, ApMode::infra);
auto ap2 = createAccessPoint("2", "JDR", device, 20, Secure::wpa, ApMode::adhoc);
auto ap3 = createAccessPoint("3", "DGN", device, 40, Secure::wpa, ApMode::infra);
auto ap4 = createAccessPoint("4", "JDY", device, 60, Secure::wpa, ApMode::adhoc);
auto ap5 = createAccessPoint("5", "SCE", device, 20, Secure::insecure, ApMode::infra);
auto ap6 = createAccessPoint("6", "ADS", device, 40, Secure::insecure, ApMode::adhoc);
auto ap7 = createAccessPoint("7", "CFT", device, 60, Secure::insecure, ApMode::infra);
auto ap8 = createAccessPoint("8", "GDF", device, 80, Secure::insecure, ApMode::adhoc);
// connect to 2-bar secure AP
auto connection = createAccessPointConnection("3", "DGN", device);
auto active_connection = createActiveConnection("3", device, connection, ap3);
// start the indicator
ASSERT_NO_THROW(startIndicator());
// set sim unlocked on carrier with 3-bar signal
setNetworkRegistrationProperty(firstModem(), "Strength", QVariant::fromValue(uchar(26)));
// check that the wifi switch is on
// check indicator is a 3-bar signal icon and 2-bar locked wifi icon
// check sim status shows correct carrier name with 3-bar signal icon.
// check that AP list contains the connected AP at top then other APs underneath in alphabetical order.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-high", "nm-signal-50-secure"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "fake.tel", "gsm-3g-high"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.section()
.item(accessPoint("DGN", Secure::wpa, ApMode::infra, ConnectionStatus::connected, 40))
.item(accessPoint("ADS", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 40))
.item(accessPoint("CFT", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 60))
.item(accessPoint("GDF", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 80))
.item(accessPoint("JDR", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 20))
.item(accessPoint("JDY", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 60))
.item(accessPoint("NSD", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 0))
.item(accessPoint("SCE", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 20))
)
).match());
// set wifi off
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch(true)
.activate()
)
).match());
setGlobalConnectedState(NM_STATE_DISCONNECTED);
removeActiveConnection(device, active_connection);
removeWifiConnection(device, connection);
removeAccessPoint(device, ap1);
removeAccessPoint(device, ap2);
removeAccessPoint(device, ap3);
removeAccessPoint(device, ap4);
removeAccessPoint(device, ap5);
removeAccessPoint(device, ap6);
removeAccessPoint(device, ap7);
removeAccessPoint(device, ap8);
// check that the flight mode switch is still off
// check that the wifi switch is off
// check indicator is a 3-bar signal icon and 0-bar wifi icon
// check sim status shows correct carrier name with 3-bar signal icon.
// check that AP list is empty
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-high", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "fake.tel", "gsm-3g-high"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(false))
.item(mh::MenuItemMatcher()
.is_empty()
)
).match());
// set flight mode on
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false)
.activate()
)
).match());
setModemProperty(firstModem(), "Online", false);
// check indicator is a plane icon and a 0-bar wifi icon
// check sim status shows “Offline” with 0-bar signal icon.
// check that AP list is empty
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"airplane-mode", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(true))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "Offline", "gsm-3g-disabled"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(false))
.item(mh::MenuItemMatcher()
.is_empty()
)
).match());
// set flight mode off
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(true)
.activate()
)
).match());
setModemProperty(firstModem(), "Online", true);
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
setConnectionManagerProperty(firstModem(), "Bearer", "gprs");
setConnectionManagerProperty(firstModem(), "Powered", true);
// check that the wifi switch is still off
// check indicator is a 3-bar signal icon and 0-bar wifi icon
// check sim status shows correct carrier name with 3-bar signal icon.
// check that AP list is empty
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-high", "network-cellular-pre-edge"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "fake.tel", "gsm-3g-high", false, "network-cellular-pre-edge"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(false))
.item(mh::MenuItemMatcher()
.is_empty()
)
).match());
}
TEST_F(TestIndicator, FlightMode_WifiOn)
{
// set wifi on, flight mode off
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// add some APs (secure / unsecure / adhoc / varied strength)
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
auto ap1 = createAccessPoint("1", "NSD", device, 0, Secure::wpa, ApMode::infra);
auto ap2 = createAccessPoint("2", "JDR", device, 20, Secure::wpa, ApMode::adhoc);
auto ap3 = createAccessPoint("3", "DGN", device, 40, Secure::wpa, ApMode::infra);
auto ap4 = createAccessPoint("4", "JDY", device, 60, Secure::wpa, ApMode::adhoc);
auto ap5 = createAccessPoint("5", "SCE", device, 20, Secure::insecure, ApMode::infra);
auto ap6 = createAccessPoint("6", "ADS", device, 40, Secure::insecure, ApMode::adhoc);
auto ap7 = createAccessPoint("7", "CFT", device, 60, Secure::insecure, ApMode::infra);
auto ap8 = createAccessPoint("8", "GDF", device, 80, Secure::insecure, ApMode::adhoc);
// connect to 4-bar insecure AP
auto connection = createAccessPointConnection("8", "GDF", device);
auto active_connection = createActiveConnection("8", device, connection, ap8);
// start the indicator
ASSERT_NO_THROW(startIndicator());
// set sim unlocked on carrier with 1-bar signal
setNetworkRegistrationProperty(firstModem(), "Strength", QVariant::fromValue(uchar(6)));
// check that the wifi switch is on
// check indicator is a 1-bar signal icon and 4-bar wifi icon
// check sim status shows correct carrier name with 1-bar signal icon.
// check that AP list contains the connected AP at top then other APs underneath in alphabetical order.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-low", "nm-signal-100"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "fake.tel", "gsm-3g-low"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("GDF", Secure::insecure, ApMode::adhoc, ConnectionStatus::connected, 80))
.item(accessPoint("ADS", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 40))
.item(accessPoint("CFT", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 60))
.item(accessPoint("DGN", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 40))
.item(accessPoint("JDR", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 20))
.item(accessPoint("JDY", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 60))
.item(accessPoint("NSD", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 0))
.item(accessPoint("SCE", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 20))
)
).match());
// set flight mode on
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false)
.activate()
)
).match());
setModemProperty(firstModem(), "Online", false);
setGlobalConnectedState(NM_STATE_DISCONNECTED);
removeActiveConnection(device, active_connection);
removeWifiConnection(device, connection);
removeAccessPoint(device, ap1);
removeAccessPoint(device, ap2);
removeAccessPoint(device, ap3);
removeAccessPoint(device, ap4);
removeAccessPoint(device, ap5);
removeAccessPoint(device, ap6);
removeAccessPoint(device, ap7);
removeAccessPoint(device, ap8);
// check that the wifi switch turns off
// check indicator is a plane icon and a 0-bar wifi icon
// check sim status shows “Offline” with 0-bar signal icon.
// check that AP list is empty
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"airplane-mode", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(true))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "Offline", "gsm-3g-disabled"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(false))
.item(mh::MenuItemMatcher()
.is_empty()
)
).match());
// set wifi on
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(true))
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch(false)
.activate()
)
).match());
// NOTE: every newly created access point increments AP index (see: AccessPointItem::Private::ConstructL())
// so here we need to start at index 1+8 as we've had 8 APs previously.
ap1 = createAccessPoint("9", "NSD", device, 0, Secure::wpa, ApMode::infra);
ap2 = createAccessPoint("10", "JDR", device, 20, Secure::wpa, ApMode::adhoc);
ap3 = createAccessPoint("11", "DGN", device, 40, Secure::wpa, ApMode::infra);
ap4 = createAccessPoint("12", "JDY", device, 60, Secure::wpa, ApMode::adhoc);
ap5 = createAccessPoint("13", "SCE", device, 20, Secure::insecure, ApMode::infra);
ap6 = createAccessPoint("14", "ADS", device, 40, Secure::insecure, ApMode::adhoc);
ap7 = createAccessPoint("15", "CFT", device, 60, Secure::insecure, ApMode::infra);
ap8 = createAccessPoint("16", "GDF", device, 80, Secure::insecure, ApMode::adhoc);
connection = createAccessPointConnection("16", "GDF", device);
active_connection = createActiveConnection("16", device, connection, ap8);
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// check that the flight mode switch is still on
// check that the wifi switch is on
// check indicator is a plane icon and a 4-bar wifi icon
// check sim status shows “Offline” with 0-bar signal icon.
// check that AP list contains the connected AP highlighted at top then other APs underneath in alphabetical order.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"airplane-mode", "nm-signal-100"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(true))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "Offline", "gsm-3g-disabled"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("GDF", Secure::insecure, ApMode::adhoc, ConnectionStatus::connected, 80))
.item(accessPoint("ADS", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 40))
.item(accessPoint("CFT", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 60))
.item(accessPoint("DGN", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 40))
.item(accessPoint("JDR", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 20))
.item(accessPoint("JDY", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 60))
.item(accessPoint("NSD", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 0))
.item(accessPoint("SCE", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 20))
)
).match());
// set flight mode off
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(true)
.activate()
)
).match());
setModemProperty(firstModem(), "Online", true);
// check that the wifi switch remains on
// check indicator is a 1-bar signal icon and 4-bar wifi icon
// check sim status shows correct carrier name with 1-bar signal icon.
// check that AP list contains the connected AP highlighted at top then other APs underneath in alphabetical order.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-low", "nm-signal-100"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "fake.tel", "gsm-3g-low"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("GDF", Secure::insecure, ApMode::adhoc, ConnectionStatus::connected, 80))
.item(accessPoint("ADS", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 40))
.item(accessPoint("CFT", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 60))
.item(accessPoint("DGN", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 40))
.item(accessPoint("JDR", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 20))
.item(accessPoint("JDY", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 60))
.item(accessPoint("NSD", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 0))
.item(accessPoint("SCE", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 20))
)
).match());
}
TEST_F(TestIndicator, GroupedWiFiAccessPoints)
{
// set wifi on, flight mode off
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// create the wifi device
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
// start the indicator
ASSERT_NO_THROW(startIndicator());
// add a single AP
auto ap1 = createAccessPoint("1", "groupA", device, 40, Secure::wpa, ApMode::infra);
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch())
.item(mh::MenuItemMatcher()
.section()
.item(accessPoint("groupA", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 40))
)
).match());
// add a second AP with the same SSID
auto ap2 = createAccessPoint("2", "groupA", device, 60, Secure::wpa, ApMode::infra);
// check that we see a single AP with the higher strength
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch())
.item(mh::MenuItemMatcher()
.section()
.item(accessPoint("groupA", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 60))
)
).match());
// up the strength of the first AP
setNmProperty(ap1, NM_DBUS_INTERFACE_ACCESS_POINT, "Strength", QVariant::fromValue(uchar(80)));
// check that we see a single AP with the higher strength
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch())
.item(mh::MenuItemMatcher()
.section()
.item(accessPoint("groupA", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 80))
)
).match());
// add another AP with a different SSID
auto ap3 = createAccessPoint("3", "groupB", device, 75, Secure::wpa, ApMode::infra);
// check that we see a single AP with the higher strength
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch())
.item(mh::MenuItemMatcher()
.section()
.item(accessPoint("groupA", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 80))
.item(accessPoint("groupB", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 75))
)
).match());
// remove the first access point
removeAccessPoint(device, ap1);
// verify the list has the old combined access point and the strength matches the second ap initial strength
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch())
.item(mh::MenuItemMatcher()
.section()
.item(accessPoint("groupA", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 60))
.item(accessPoint("groupB", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 75))
)
).match());
}
TEST_F(TestIndicator, WifiStates_SSIDs)
{
// set wifi on, flight mode off
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// add some APs (secure / unsecure / adhoc / varied strength)
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
// prepend a non-utf8 character to the end of AP 1's SSID
auto ap1 = createAccessPoint("1", "NSD", device, 20, Secure::wpa, ApMode::infra);
setNmProperty(ap1, NM_DBUS_INTERFACE_ACCESS_POINT, "Ssid", QByteArray(1, -1) + QByteArray("NSD"));
// append a non-utf8 character to the end of AP 2's SSID
auto ap2 = createAccessPoint("2", "DGN", device, 20, Secure::wpa, ApMode::infra);
setNmProperty(ap2, NM_DBUS_INTERFACE_ACCESS_POINT, "Ssid", QByteArray("DGN") + QByteArray(1, -1));
// insert a non-utf8 character into AP 3's SSID
auto ap3 = createAccessPoint("3", "JDY", device, 20, Secure::wpa, ApMode::infra);
setNmProperty(ap3, NM_DBUS_INTERFACE_ACCESS_POINT, "Ssid", QByteArray("JD") + QByteArray(1, -1) + QByteArray("Y"));
// use only non-utf8 characters for AP 4's SSID
auto ap4 = createAccessPoint("4", "---", device, 20, Secure::wpa, ApMode::infra);
setNmProperty(ap4, NM_DBUS_INTERFACE_ACCESS_POINT, "Ssid", QByteArray(4, -1));
// leave AP 5's SSID blank
auto ap5 = createAccessPoint("5", "", device, 20, Secure::wpa, ApMode::infra);
// start the indicator
ASSERT_NO_THROW(startIndicator());
// check indicator is just a mobile data connection (we are not connected to WiFi)
// check that AP list contains the 4 APs in alphabetical order.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-full"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "fake.tel", "gsm-3g-full"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("DGN�", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 20))
.item(accessPoint("JD�Y", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 20))
.item(accessPoint("�NSD", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 20))
.item(accessPoint("����", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 20))
)
).match());
}
TEST_F(TestIndicator, WifiStates_Connect1AP)
{
// create a wifi device
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
// start the indicator
ASSERT_NO_THROW(startIndicator());
// set wifi off
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch(true)
.activate()
)
).match());
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// set no sim
setSimManagerProperty(firstModem(), "Present", false);
// check indicator is just a 0-bar wifi icon
// check that AP list is empty
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "No SIM", "no-simcard"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(false))
.item(mh::MenuItemMatcher()
.is_empty()
)
).match());
// set wifi switch on and add some APs (secure/unsecure/adhoc/varied strength)
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch(false)
.activate()
)
).match());
auto ap1 = createAccessPoint("1", "NSD", device, 20, Secure::wpa, ApMode::infra);
auto ap2 = createAccessPoint("2", "JDR", device, 40, Secure::wpa, ApMode::adhoc);
auto ap3 = createAccessPoint("3", "DGN", device, 60, Secure::wpa, ApMode::infra);
auto ap4 = createAccessPoint("4", "JDY", device, 80, Secure::wpa, ApMode::adhoc);
auto ap5 = createAccessPoint("5", "SCE", device, 0, Secure::insecure, ApMode::infra);
auto ap6 = createAccessPoint("6", "ADS", device, 20, Secure::insecure, ApMode::adhoc);
auto ap7 = createAccessPoint("7", "CFT", device, 40, Secure::insecure, ApMode::infra);
auto ap8 = createAccessPoint("8", "GDF", device, 60, Secure::insecure, ApMode::adhoc);
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// check indicator is empty (we aren't connected to WiFi)
// check that AP list contains available APs in alphabetical order (with correct signal and security icons).
// check AP items have the correct associated action names.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "No SIM", "no-simcard"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("ADS", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 20))
.item(accessPoint("CFT", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 40))
.item(accessPoint("DGN", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 60))
.item(accessPoint("GDF", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 60))
.item(accessPoint("JDR", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 40))
.item(accessPoint("JDY", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 80))
.item(accessPoint("NSD", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 20))
.item(accessPoint("SCE", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 0))
)
).match());
// connect to 1-bar unsecure AP
setGlobalConnectedState(NM_STATE_CONNECTING);
auto connection = createAccessPointConnection("6", "ADS", device);
auto active_connection = createActiveConnection("6", device, connection, ap6);
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// check indicator is just a 1-bar wifi icon
// check that AP list contains the connected AP highlighted at top then other APs underneath in alphabetical order.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-signal-25"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false)).item(mh::MenuItemMatcher()).item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("ADS", Secure::insecure, ApMode::adhoc, ConnectionStatus::connected, 20))
.item(accessPoint("CFT", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 40))
.item(accessPoint("DGN", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 60))
.item(accessPoint("GDF", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 60))
.item(accessPoint("JDR", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 40))
.item(accessPoint("JDY", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 80))
.item(accessPoint("NSD", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 20))
.item(accessPoint("SCE", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 0))
)
).match());
// set AP signal strength 0
setNmProperty(ap6, NM_DBUS_INTERFACE_ACCESS_POINT, "Strength", QVariant::fromValue(uchar(0)));
// check indicator is a 0-bar wifi icon.
// check that AP signal icon also updates accordingly.
auto ap_item = mh::MenuItemMatcher::checkbox();
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-signal-00"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false)).item(mh::MenuItemMatcher()).item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("ADS", Secure::insecure, ApMode::adhoc, ConnectionStatus::connected, 0))
.item(ap_item).item(ap_item).item(ap_item).item(ap_item).item(ap_item).item(ap_item).item(ap_item)
)
).match());
// set AP signal strength 40
setNmProperty(ap6, NM_DBUS_INTERFACE_ACCESS_POINT, "Strength", QVariant::fromValue(uchar(40)));
// check indicator is a 2-bar wifi icon.
// check that AP signal icon also updates accordingly.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-signal-50"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false)).item(mh::MenuItemMatcher()).item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("ADS", Secure::insecure, ApMode::adhoc, ConnectionStatus::connected, 40))
.item(ap_item).item(ap_item).item(ap_item).item(ap_item).item(ap_item).item(ap_item).item(ap_item)
)
).match());
// set AP signal strength 60
setNmProperty(ap6, NM_DBUS_INTERFACE_ACCESS_POINT, "Strength", QVariant::fromValue(uchar(60)));
// check indicator is a 3-bar wifi icon.
// check that AP signal icon also updates accordingly.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-signal-75"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false)).item(mh::MenuItemMatcher()).item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("ADS", Secure::insecure, ApMode::adhoc, ConnectionStatus::connected, 60))
.item(ap_item).item(ap_item).item(ap_item).item(ap_item).item(ap_item).item(ap_item).item(ap_item)
)
).match());
// set AP signal strength 80
setNmProperty(ap6, NM_DBUS_INTERFACE_ACCESS_POINT, "Strength", QVariant::fromValue(uchar(80)));
// check indicator is a 4-bar wifi icon.
// check that AP signal icon also updates accordingly.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-signal-100"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false)).item(mh::MenuItemMatcher()).item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("ADS", Secure::insecure, ApMode::adhoc, ConnectionStatus::connected, 80))
.item(ap_item).item(ap_item).item(ap_item).item(ap_item).item(ap_item).item(ap_item).item(ap_item)
)
).match());
// set wifi off
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch(true)
.activate()
)
).match());
setGlobalConnectedState(NM_STATE_DISCONNECTED);
removeActiveConnection(device, active_connection);
removeWifiConnection(device, connection);
removeAccessPoint(device, ap1);
removeAccessPoint(device, ap2);
removeAccessPoint(device, ap3);
removeAccessPoint(device, ap4);
removeAccessPoint(device, ap5);
removeAccessPoint(device, ap6);
removeAccessPoint(device, ap7);
removeAccessPoint(device, ap8);
// check indicator is just a 0-bar wifi icon
// check that AP list is empty
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false)).item(mh::MenuItemMatcher()).item(wifiEnableSwitch(false))
.item(mh::MenuItemMatcher()
.is_empty()
)
).match());
}
TEST_F(TestIndicator, WifiStates_Connect2APs)
{
// set wifi on, flight mode off
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// set no sim
setSimManagerProperty(firstModem(), "Present", false);
// add some APs (secure / unsecure / adhoc / varied strength)
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
auto ap1 = createAccessPoint("1", "NSD", device, 20, Secure::wpa, ApMode::infra);
auto ap2 = createAccessPoint("2", "JDR", device, 40, Secure::wpa, ApMode::adhoc);
auto ap3 = createAccessPoint("3", "DGN", device, 60, Secure::wpa, ApMode::infra);
auto ap4 = createAccessPoint("4", "JDY", device, 80, Secure::wpa, ApMode::adhoc);
auto ap5 = createAccessPoint("5", "SCE", device, 0, Secure::insecure, ApMode::infra);
auto ap6 = createAccessPoint("6", "ADS", device, 20, Secure::insecure, ApMode::adhoc);
auto ap7 = createAccessPoint("7", "CFT", device, 40, Secure::insecure, ApMode::infra);
auto ap8 = createAccessPoint("8", "GDF", device, 60, Secure::insecure, ApMode::adhoc);
// connect to 4-bar secure AP
auto connection = createAccessPointConnection("4", "JDY", device);
auto active_connection = createActiveConnection("4", device, connection, ap4);
// start the indicator
ASSERT_NO_THROW(startIndicator());
// check indicator is just a 4-bar locked wifi icon
// check that AP list contains the connected AP highlighted at top then other APs underneath in alphabetical order.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-signal-100-secure"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "No SIM", "no-simcard"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("JDY", Secure::wpa, ApMode::adhoc, ConnectionStatus::connected, 80))
.item(accessPoint("ADS", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 20))
.item(accessPoint("CFT", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 40))
.item(accessPoint("DGN", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 60))
.item(accessPoint("GDF", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 60))
.item(accessPoint("JDR", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 40))
.item(accessPoint("NSD", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 20))
.item(accessPoint("SCE", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 0))
)
).match());
// connect to 2-bar unsecure AP
setGlobalConnectedState(NM_STATE_DISCONNECTED);
removeActiveConnection(device, active_connection);
removeWifiConnection(device, connection);
setGlobalConnectedState(NM_STATE_CONNECTING);
connection = createAccessPointConnection("7", "CFT", device);
active_connection = createActiveConnection("7", device, connection, ap7);
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// check indicator is just a 2-bar wifi icon
// check that AP list contains the connected AP highlighted at top then other APs underneath in alphabetical order.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-signal-50"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false)).item(mh::MenuItemMatcher()).item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("CFT", Secure::insecure, ApMode::infra, ConnectionStatus::connected, 40))
.item(accessPoint("ADS", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 20))
.item(accessPoint("DGN", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 60))
.item(accessPoint("GDF", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 60))
.item(accessPoint("JDR", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 40))
.item(accessPoint("JDY", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 80))
.item(accessPoint("NSD", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 20))
.item(accessPoint("SCE", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 0))
)
).match());
// set wifi off
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch(true)
.activate()
)
).match());
setGlobalConnectedState(NM_STATE_DISCONNECTED);
removeActiveConnection(device, active_connection);
removeWifiConnection(device, connection);
removeAccessPoint(device, ap1);
removeAccessPoint(device, ap2);
removeAccessPoint(device, ap3);
removeAccessPoint(device, ap4);
removeAccessPoint(device, ap5);
removeAccessPoint(device, ap6);
removeAccessPoint(device, ap7);
removeAccessPoint(device, ap8);
// check indicator is just a 0-bar wifi icon
// check that AP list is empty
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false)).item(mh::MenuItemMatcher()).item(wifiEnableSwitch(false))
.item(mh::MenuItemMatcher()
.is_empty()
)
).match());
// set wifi on
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch(false)
.activate()
)
).match());
// NOTE: every newly created access point increments AP index (see: AccessPointItem::Private::ConstructL())
// so here we need to start at index 1+8 as we've had 8 APs previously.
ap1 = createAccessPoint("9", "NSD", device, 20, Secure::wpa, ApMode::infra);
ap2 = createAccessPoint("10", "JDR", device, 40, Secure::wpa, ApMode::adhoc);
ap3 = createAccessPoint("11", "DGN", device, 60, Secure::wpa, ApMode::infra);
ap4 = createAccessPoint("12", "JDY", device, 80, Secure::wpa, ApMode::adhoc);
ap5 = createAccessPoint("13", "SCE", device, 0, Secure::insecure, ApMode::infra);
ap6 = createAccessPoint("14", "ADS", device, 20, Secure::insecure, ApMode::adhoc);
ap7 = createAccessPoint("15", "CFT", device, 40, Secure::insecure, ApMode::infra);
ap8 = createAccessPoint("16", "GDF", device, 60, Secure::insecure, ApMode::adhoc);
connection = createAccessPointConnection("12", "JDY", device);
active_connection = createActiveConnection("12", device, connection, ap4);
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// check that the 4-bar secure AP is reconnected (as it has the highest signal).
// check indicator is just a 4-bar locked wifi icon
// check that AP list contains the connected AP highlighted at top then other APs underneath in alphabetical order.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-signal-100-secure"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false)).item(mh::MenuItemMatcher()).item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("JDY", Secure::wpa, ApMode::adhoc, ConnectionStatus::connected, 80))
.item(accessPoint("ADS", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 20))
.item(accessPoint("CFT", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 40))
.item(accessPoint("DGN", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 60))
.item(accessPoint("GDF", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 60))
.item(accessPoint("JDR", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 40))
.item(accessPoint("NSD", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 20))
.item(accessPoint("SCE", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 0))
)
).match());
}
TEST_F(TestIndicator, WifiStates_AddAndActivate)
{
// set wifi on, flight mode off
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// set no sim
setSimManagerProperty(firstModem(), "Present", false);
// add some APs (secure / unsecure / adhoc / varied strength)
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
auto ap1 = createAccessPoint("1", "NSD", device, 40, Secure::wpa, ApMode::infra);
auto ap2 = createAccessPoint("2", "JDR", device, 40, Secure::wpa, ApMode::adhoc);
auto ap3 = createAccessPoint("3", "DGN", device, 60, Secure::wpa, ApMode::infra);
auto ap4 = createAccessPoint("4", "JDY", device, 80, Secure::wpa, ApMode::adhoc);
auto ap5 = createAccessPoint("5", "SCE", device, 20, Secure::insecure, ApMode::infra);
auto ap6 = createAccessPoint("6", "ADS", device, 20, Secure::insecure, ApMode::adhoc);
auto ap7 = createAccessPoint("7", "CFT", device, 40, Secure::insecure, ApMode::infra);
auto ap8 = createAccessPoint("8", "GDF", device, 60, Secure::insecure, ApMode::adhoc);
// start the indicator
ASSERT_NO_THROW(startIndicator());
// check indicator is just a 0-bar wifi icon
// check that AP list contains the APs in alphabetical order.
// activate the "SCE" AP (AddAndActivateConnection)
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "No SIM", "no-simcard"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("ADS", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 20))
.item(accessPoint("CFT", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 40))
.item(accessPoint("DGN", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 60))
.item(accessPoint("GDF", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 60))
.item(accessPoint("JDR", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 40))
.item(accessPoint("JDY", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 80))
.item(accessPoint("NSD", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 40))
.item(accessPoint("SCE", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 20)
.activate())
)
).match());
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// check indicator is just a 1-bar wifi icon
// check that AP list contains the connected AP highlighted at top then other APs underneath in alphabetical order.
// activate the "NSD" AP (AddAndActivateConnection)
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-signal-25"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "No SIM", "no-simcard"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("SCE", Secure::insecure, ApMode::infra, ConnectionStatus::connected, 20))
.item(accessPoint("ADS", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 20))
.item(accessPoint("CFT", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 40))
.item(accessPoint("DGN", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 60))
.item(accessPoint("GDF", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 60))
.item(accessPoint("JDR", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 40))
.item(accessPoint("JDY", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 80))
.item(accessPoint("NSD", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 40)
.activate())
)
).match());
setGlobalConnectedState(NM_STATE_CONNECTING);
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// check indicator is just a 2-bar locked wifi icon
// check that AP list contains the connected AP highlighted at top then other APs underneath in alphabetical order.
// re-activate the "SCE" AP (ActivateConnection)
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-signal-50-secure"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "No SIM", "no-simcard"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("NSD", Secure::wpa, ApMode::infra, ConnectionStatus::connected, 40))
.item(accessPoint("ADS", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 20))
.item(accessPoint("CFT", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 40))
.item(accessPoint("DGN", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 60))
.item(accessPoint("GDF", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 60))
.item(accessPoint("JDR", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 40))
.item(accessPoint("JDY", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 80))
.item(accessPoint("SCE", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 20)
.activate())
)
).match());
setGlobalConnectedState(NM_STATE_CONNECTING);
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// check indicator is just a 1-bar wifi icon
// check that AP list contains the connected AP highlighted at top then other APs underneath in alphabetical order.
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-signal-25"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "No SIM", "no-simcard"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("SCE", Secure::insecure, ApMode::infra, ConnectionStatus::connected, 20))
.item(accessPoint("ADS", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 20))
.item(accessPoint("CFT", Secure::insecure, ApMode::infra, ConnectionStatus::disconnected, 40))
.item(accessPoint("DGN", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 60))
.item(accessPoint("GDF", Secure::insecure, ApMode::adhoc, ConnectionStatus::disconnected, 60))
.item(accessPoint("JDR", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 40))
.item(accessPoint("JDY", Secure::wpa, ApMode::adhoc, ConnectionStatus::disconnected, 80))
.item(accessPoint("NSD", Secure::wpa, ApMode::infra, ConnectionStatus::disconnected, 40))
)
).match());
}
TEST_F(TestIndicator, EnterpriseWifiConnect)
{
// set wifi on, flight mode off
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// set no sim
setSimManagerProperty(firstModem(), "Present", false);
// add some APs (secure / unsecure / adhoc / varied strength)
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
auto ap1 = createAccessPoint("1", "ABC", device, 80, Secure::wpa_enterprise, ApMode::infra, "11:22:33:44:55:66");
// start the indicator
ASSERT_NO_THROW(startIndicator());
// interface to the URL dispatcher
auto& urlDispatcher = dbusMock.mockInterface(
"com.canonical.URLDispatcher",
"/com/canonical/URLDispatcher",
"com.canonical.URLDispatcher",
QDBusConnection::SessionBus);
// Wait for method calls on the URL dispatcher
QSignalSpy urlDispatcherSpy(&urlDispatcher, SIGNAL(MethodCalled(const QString &, const QVariantList &)));
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch(false))
.item(mh::MenuItemMatcher()
.item(modemInfo("", "No SIM", "no-simcard"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("ABC", Secure::wpa_enterprise, ApMode::infra, ConnectionStatus::disconnected, 80).activate())
)
).match());
if (urlDispatcherSpy.isEmpty())
{
ASSERT_TRUE(urlDispatcherSpy.wait());
}
ASSERT_FALSE(urlDispatcherSpy.isEmpty());
EXPECT_EQ(urlDispatcherSpy.first(),
QVariantList()
<< QVariant("DispatchURL")
<< QVariant(
QVariantList()
<< QVariant("settings:///system/wifi?ssid=ABC&bssid=11:22:33:44:55:66")
<< QVariant("")
)
);
}
TEST_F(TestIndicator, CellDataEnabled)
{
// We are connected
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// Create a WiFi device and power it off
auto device = createWiFiDevice(NM_DEVICE_STATE_DISCONNECTED);
disableWiFi();
// sim in with carrier and 4-bar signal and HSPA
setNetworkRegistrationProperty(firstModem(), "Strength", QVariant::fromValue(uchar(26)));
setConnectionManagerProperty(firstModem(), "Bearer", "hspa");
setModemProperty(firstModem(), "Online", true);
setConnectionManagerProperty(firstModem(), "Powered", true);
// second sim with umts (3G)
auto secondModem = createModem("ril_1");
setNetworkRegistrationProperty(secondModem, "Strength", QVariant::fromValue(uchar(6)));
setConnectionManagerProperty(secondModem, "Bearer", "umts");
setModemProperty(secondModem, "Online", true);
setConnectionManagerProperty(secondModem, "Powered", false);
ASSERT_NO_THROW(startIndicator());
// Should be connected to HSPA
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-high", "gsm-3g-low", "network-cellular-hspa"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-high", false, "network-cellular-hspa"))
.item(modemInfo("SIM 2", "fake.tel", "gsm-3g-low"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(false))
).match());
// First SIM card now only has EDGE
setConnectionManagerProperty(firstModem(), "Bearer", "edge");
// Now we should have an EDGE icon
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-high", "gsm-3g-low", "network-cellular-edge"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-high", false, "network-cellular-edge"))
.item(modemInfo("SIM 2", "fake.tel", "gsm-3g-low"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(false))
).match());
// Set second SIM as the active data connection
setConnectionManagerProperty(firstModem(), "Powered", false);
setConnectionManagerProperty(secondModem, "Powered", true);
// Now we should have a 3G icon
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-high", "gsm-3g-low", "network-cellular-3g"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-high"))
.item(modemInfo("SIM 2", "fake.tel", "gsm-3g-low", false, "network-cellular-3g"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(false))
).match());
}
TEST_F(TestIndicator, CellDataDisabled)
{
// We are disconnected
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// Create a WiFi device and power it off
auto device = createWiFiDevice(NM_DEVICE_STATE_DISCONNECTED);
disableWiFi();
// sim in with carrier and 1-bar signal and HSPA, data disabled
setNetworkRegistrationProperty(firstModem(), "Strength", QVariant::fromValue(uchar(6)));
setConnectionManagerProperty(firstModem(), "Bearer", "hspa");
setModemProperty(firstModem(), "Online", true);
setConnectionManagerProperty(firstModem(), "Powered", false);
// second sim with 4-bar signal umts (3G), data disabled
auto secondModem = createModem("ril_1");
setNetworkRegistrationProperty(secondModem, "Strength", QVariant::fromValue(uchar(26)));
setConnectionManagerProperty(secondModem, "Bearer", "umts");
setModemProperty(secondModem, "Online", true);
setConnectionManagerProperty(secondModem, "Powered", false);
ASSERT_NO_THROW(startIndicator());
// Should be totally disconnected
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-low", "gsm-3g-high", "nm-no-connection"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-low"))
.item(modemInfo("SIM 2", "fake.tel", "gsm-3g-high"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(false))
).match());
// Set second SIM as the active data connection
setGlobalConnectedState(NM_STATE_CONNECTING);
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
setConnectionManagerProperty(firstModem(), "Powered", false);
setConnectionManagerProperty(secondModem, "Powered", true);
// Should be connected to 3G
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-low", "gsm-3g-high", "network-cellular-3g"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-low"))
.item(modemInfo("SIM 2", "fake.tel", "gsm-3g-high", false, "network-cellular-3g"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(false))
).match());
// Enable WiFi and connect to it
enableWiFi();
auto ap1 = createAccessPoint("1", "ABC", device, 20, Secure::wpa, ApMode::infra);
auto connection = createAccessPointConnection("1", "ABC", device);
setNmProperty(device, NM_DBUS_INTERFACE_DEVICE, "State", QVariant::fromValue(uint(NM_DEVICE_STATE_ACTIVATED)));
auto active_connection = createActiveConnection("1", device, connection, ap1);
setGlobalConnectedState(NM_STATE_CONNECTING);
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
// Should be connected to WiFi
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.state_icons({"gsm-3g-low", "gsm-3g-high", "nm-signal-25-secure"})
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-low"))
.item(modemInfo("SIM 2", "fake.tel", "gsm-3g-high", false, "network-cellular-3g"))
.item(cellularSettings())
)
.item(wifiEnableSwitch(true))
.item(mh::MenuItemMatcher()
.item(accessPoint("ABC",
Secure::wpa,
ApMode::infra,
ConnectionStatus::connected,
20)
)
)
).match());
}
TEST_F(TestIndicator, UnlockSIM_MenuContents)
{
// set flight mode off, wifi off, and cell data off, and sim in
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// set sim locked
setSimManagerProperty(firstModem(), "PinRequired", "pin");
QSignalSpy notificationsSpy(¬ificationsMockInterface(),
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
// start the indicator
ASSERT_NO_THROW(startIndicator());
// check indicator is a locked sim card and a 0-bar wifi icon.
// check sim status shows “SIM Locked”, with locked sim card icon and a “Unlock SIM” button beneath.
// check that the “Unlock SIM” button has the correct action name.
// activate “Unlock SIM” action
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("", "SIM Locked", "simcard-locked", true)
.pass_through_activate("x-canonical-modem-locked-action")
)
.item(cellularSettings())
)
).match());
// check that the "GetServerInformation" method was called
// check method arguments are correct
string busName;
WAIT_FOR_SIGNALS(notificationsSpy, 2);
{
QVariantList const& call(notificationsSpy.at(0));
EXPECT_EQ("GetServerInformation", call.at(0));
QVariantList const& args(call.at(1).toList());
ASSERT_EQ(0, args.size());
}
{
QVariantList const& call(notificationsSpy.at(1));
EXPECT_EQ("Notify", call.at(0));
QVariantList const& args(call.at(1).toList());
ASSERT_EQ(8, args.size());
EXPECT_EQ("indicator-network", args.at(0));
EXPECT_EQ(0, args.at(1));
EXPECT_EQ("", args.at(2));
EXPECT_EQ("Enter SIM PIN", args.at(3));
EXPECT_EQ("3 attempts remaining", args.at(4));
EXPECT_EQ(QStringList(), args.at(5));
EXPECT_EQ(-1, args.at(7));
QVariantMap hints;
ASSERT_TRUE(qDBusArgumentToMap(args.at(6), hints));
ASSERT_EQ(3, hints.size());
ASSERT_TRUE(hints.contains("x-canonical-private-menu-model"));
ASSERT_TRUE(hints.contains("x-canonical-snap-decisions"));
ASSERT_TRUE(hints.contains("x-canonical-snap-decisions-timeout"));
EXPECT_EQ(true, hints["x-canonical-snap-decisions"]);
EXPECT_EQ(numeric_limits::max(), hints["x-canonical-snap-decisions-timeout"]);
QVariantMap menuInfo;
ASSERT_TRUE(qDBusArgumentToMap(hints["x-canonical-private-menu-model"], menuInfo));
ASSERT_EQ(3, menuInfo.size());
ASSERT_TRUE(menuInfo.contains("actions"));
ASSERT_TRUE(menuInfo.contains("busName"));
ASSERT_TRUE(menuInfo.contains("menuPath"));
busName = menuInfo["busName"].toString().toStdString();
EXPECT_EQ("/com/canonical/indicator/network/unlocksim0", menuInfo["menuPath"]);
QVariantMap actions;
ASSERT_TRUE(qDBusArgumentToMap(menuInfo["actions"], actions));
ASSERT_EQ(1, actions.size());
ASSERT_TRUE(actions.contains("notifications"));
EXPECT_EQ("/com/canonical/indicator/network/unlocksim0", actions["notifications"]);
}
notificationsSpy.clear();
ASSERT_FALSE(busName.empty());
// check contents of x-canonical-private-menu-model
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.action("notifications.simunlock")
.string_attribute("x-canonical-type", "com.canonical.snapdecision.pinlock")
.string_attribute("x-canonical-pin-min-max", "notifications.pinMinMax")
.string_attribute("x-canonical-pin-popup", "notifications.popup")
.string_attribute("x-canonical-pin-error", "notifications.error")
).match());
}
TEST_F(TestIndicator, UnlockSIM_Cancel)
{
// set flight mode off, wifi off, and cell data off, and sim in
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// set sim locked
setSimManagerProperty(firstModem(), "PinRequired", "pin");
QSignalSpy notificationsSpy(¬ificationsMockInterface(),
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
// start the indicator
ASSERT_NO_THROW(startIndicator());
// check indicator is a locked sim card and a 0-bar wifi icon.
// check sim status shows “SIM Locked”, with locked sim card icon and a “Unlock SIM” button beneath.
// check that the “Unlock SIM” button has the correct action name.
// activate “Unlock SIM” action
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("", "SIM Locked", "simcard-locked", true)
.pass_through_activate("x-canonical-modem-locked-action")
)
.item(cellularSettings())
)
).match());
// check that the "GetServerInformation" method was called
// check method arguments are correct
std::string busName;
WAIT_FOR_SIGNALS(notificationsSpy, 2);
CHECK_METHOD_CALL(notificationsSpy, 0, "GetServerInformation", /* no_args */);
CHECK_METHOD_CALL(notificationsSpy, 1, "Notify", {1, 0}, {3, "Enter SIM PIN"}, {4, "3 attempts remaining"});
{
QVariantList const& call(notificationsSpy.at(1));
QVariantList const& args(call.at(1).toList());
QVariantMap hints;
QVariantMap menuInfo;
ASSERT_TRUE(qDBusArgumentToMap(args.at(6), hints));
ASSERT_TRUE(qDBusArgumentToMap(hints["x-canonical-private-menu-model"], menuInfo));
busName = menuInfo["busName"].toString().toStdString();
}
notificationsSpy.clear();
// cancel the notification
QSignalSpy notificationClosedSpy(&dbusMock.notificationDaemonInterface(),
SIGNAL(NotificationClosed(uint, uint)));
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.action("notifications.simunlock")
.string_attribute("x-canonical-type", "com.canonical.snapdecision.pinlock")
.string_attribute("x-canonical-pin-min-max", "notifications.pinMinMax")
.string_attribute("x-canonical-pin-popup", "notifications.popup")
.string_attribute("x-canonical-pin-error", "notifications.error")
.activate(shared_ptr(g_variant_new_boolean(false), &mh::gvariant_deleter))
).match());
// check that the "NotificationClosed" signal was emitted
WAIT_FOR_SIGNALS(notificationClosedSpy, 1);
EXPECT_EQ(notificationClosedSpy.first(), QVariantList() << QVariant(1) << QVariant(1));
notificationClosedSpy.clear();
// check that the "CloseNotification" method was called
// check method arguments are correct
WAIT_FOR_SIGNALS(notificationsSpy, 1);
CHECK_METHOD_CALL(notificationsSpy, 0, "CloseNotification", {0, "1"});
notificationsSpy.clear();
// re-activate “Unlock SIM” action
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("", "SIM Locked", "simcard-locked", true)
.pass_through_activate("x-canonical-modem-locked-action")
)
.item(cellularSettings())
)
).match());
// check that the "Notify" method was called
// check method arguments are correct (we re-use the same notification and reopen it)
WAIT_FOR_SIGNALS(notificationsSpy, 1);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1});
notificationsSpy.clear();
// cancel the notification again
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.action("notifications.simunlock")
.string_attribute("x-canonical-type", "com.canonical.snapdecision.pinlock")
.string_attribute("x-canonical-pin-min-max", "notifications.pinMinMax")
.string_attribute("x-canonical-pin-popup", "notifications.popup")
.string_attribute("x-canonical-pin-error", "notifications.error")
.activate(shared_ptr(g_variant_new_boolean(false), &mh::gvariant_deleter))
).match());
// check that the "NotificationClosed" signal was emitted (new notification index should be 1)
WAIT_FOR_SIGNALS(notificationClosedSpy, 1);
EXPECT_EQ(notificationClosedSpy.first(), QVariantList() << QVariant(1) << QVariant(1));
notificationClosedSpy.clear();
// check that the "CloseNotification" method was called
// check method arguments are correct (still using the same notification: 1)
WAIT_FOR_SIGNALS(notificationsSpy, 1);
CHECK_METHOD_CALL(notificationsSpy, 0, "CloseNotification", {0, "1"});
notificationsSpy.clear();
}
TEST_F(TestIndicator, UnlockSIM_CancelFirstUnlockSecond)
{
// set flight mode off, wifi off, and cell data off, and sim in
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// set sim locked
setSimManagerProperty(firstModem(), "PinRequired", "pin");
// Create a second locked modem
auto secondModem = createModem("ril_1");
setSimManagerProperty(secondModem, "PinRequired", "pin");
QSignalSpy notificationsSpy(¬ificationsMockInterface(),
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
QSignalSpy secondModemMockInterfaceSpy(&modemMockInterface(secondModem),
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
// start the indicator
ASSERT_NO_THROW(startIndicator());
// check indicator is a locked sim card and a 0-bar wifi icon.
// check sim status shows “SIM Locked”, with locked sim card icon and a “Unlock SIM” button beneath.
// check that the “Unlock SIM” button has the correct action name.
// unlock first SIM
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "SIM Locked", "simcard-locked", true)
.pass_through_activate("x-canonical-modem-locked-action")
)
.item(modemInfo("SIM 2", "SIM Locked", "simcard-locked", true))
.item(cellularSettings())
)
).match());
// check that the "GetServerInformation" method was called
// check method arguments are correct
std::string busName;
WAIT_FOR_SIGNALS(notificationsSpy, 2);
CHECK_METHOD_CALL(notificationsSpy, 0, "GetServerInformation", /* no_args */);
CHECK_METHOD_CALL(notificationsSpy, 1, "Notify", {1, 0}, {3, "Enter SIM 1 PIN"}, {4, "3 attempts remaining"});
{
QVariantList const& call(notificationsSpy.at(1));
QVariantList const& args(call.at(1).toList());
QVariantMap hints;
QVariantMap menuInfo;
ASSERT_TRUE(qDBusArgumentToMap(args.at(6), hints));
ASSERT_TRUE(qDBusArgumentToMap(hints["x-canonical-private-menu-model"], menuInfo));
busName = menuInfo["busName"].toString().toStdString();
}
notificationsSpy.clear();
// cancel the notification
QSignalSpy notificationClosedSpy(&dbusMock.notificationDaemonInterface(),
SIGNAL(NotificationClosed(uint, uint)));
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.action("notifications.simunlock")
.string_attribute("x-canonical-type", "com.canonical.snapdecision.pinlock")
.string_attribute("x-canonical-pin-min-max", "notifications.pinMinMax")
.string_attribute("x-canonical-pin-popup", "notifications.popup")
.string_attribute("x-canonical-pin-error", "notifications.error")
.activate(shared_ptr(g_variant_new_boolean(false), &mh::gvariant_deleter))
).match());
// check that the "NotificationClosed" signal was emitted
WAIT_FOR_SIGNALS(notificationClosedSpy, 1);
EXPECT_EQ(notificationClosedSpy.first(), QVariantList() << QVariant(1) << QVariant(1));
notificationClosedSpy.clear();
// check that the "CloseNotification" method was called
// check method arguments are correct
WAIT_FOR_SIGNALS(notificationsSpy, 1);
CHECK_METHOD_CALL(notificationsSpy, 0, "CloseNotification", {0, "1"});
notificationsSpy.clear();
// Activate the second SIM unlock
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "SIM Locked", "simcard-locked", true))
.item(modemInfo("SIM 2", "SIM Locked", "simcard-locked", true)
.pass_through_activate("x-canonical-modem-locked-action")
)
.item(cellularSettings())
)
).match());
// check that the "Notify" method was called
// check method arguments are correct (we re-use the same notification and reopen it)
WAIT_FOR_SIGNALS(notificationsSpy, 1);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Enter SIM 2 PIN"});
notificationsSpy.clear();
secondModemMockInterfaceSpy.clear();
// enter the PIN
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.action("notifications.simunlock")
.string_attribute("x-canonical-type", "com.canonical.snapdecision.pinlock")
.string_attribute("x-canonical-pin-min-max", "notifications.pinMinMax")
.string_attribute("x-canonical-pin-popup", "notifications.popup")
.string_attribute("x-canonical-pin-error", "notifications.error")
.set_action_state(shared_ptr(g_variant_new_string("1234"), &mh::gvariant_deleter))
).match());
// Check the PIN was sent to Ofono
WAIT_FOR_SIGNALS(secondModemMockInterfaceSpy, 1);
CHECK_METHOD_CALL(secondModemMockInterfaceSpy, 0, "EnterPin", {0, "pin"}, {1, "1234"});
// check that the "NotificationClosed" signal was emitted (new notification index should be 1)
WAIT_FOR_SIGNALS(notificationClosedSpy, 1);
EXPECT_EQ(notificationClosedSpy.first(), QVariantList() << QVariant(1) << QVariant(1));
notificationClosedSpy.clear();
// check that the "CloseNotification" method was called
// check method arguments are correct (still using the same notification: 1)
WAIT_FOR_SIGNALS(notificationsSpy, 1);
CHECK_METHOD_CALL(notificationsSpy, 0, "CloseNotification", {0, "1"});
notificationsSpy.clear();
}
TEST_F(TestIndicator, UnlockSIM_CorrectPin)
{
// set flight mode off, wifi off, and cell data off, and sim in
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// set sim locked
setSimManagerProperty(firstModem(), "PinRequired", "pin");
QSignalSpy notificationsSpy(¬ificationsMockInterface(),
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
// start the indicator
ASSERT_NO_THROW(startIndicator());
// check indicator is a locked sim card and a 0-bar wifi icon.
// check sim status shows “SIM Locked”, with locked sim card icon and a “Unlock SIM” button beneath.
// check that the “Unlock SIM” button has the correct action name.
// activate “Unlock SIM” action
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("", "SIM Locked", "simcard-locked", true)
.pass_through_activate("x-canonical-modem-locked-action")
)
.item(cellularSettings())
)
).match());
// check that the "GetServerInformation" method was called
// check that the "Notify" method was called twice
// check method arguments are correct
std::string busName;
WAIT_FOR_SIGNALS(notificationsSpy, 2);
CHECK_METHOD_CALL(notificationsSpy, 0, "GetServerInformation", /* no_args */);
CHECK_METHOD_CALL(notificationsSpy, 1, "Notify", {1, 0}, {3, "Enter SIM PIN"}, {4, "3 attempts remaining"});
{
QVariantList const& call(notificationsSpy.at(1));
QVariantList const& args(call.at(1).toList());
QVariantMap hints;
QVariantMap menuInfo;
ASSERT_TRUE(qDBusArgumentToMap(args.at(6), hints));
ASSERT_TRUE(qDBusArgumentToMap(hints["x-canonical-private-menu-model"], menuInfo));
busName = menuInfo["busName"].toString().toStdString();
}
notificationsSpy.clear();
// enter correct pin
QSignalSpy notificationClosedSpy(&dbusMock.notificationDaemonInterface(),
SIGNAL(NotificationClosed(uint, uint)));
QSignalSpy modemSpy(&modemMockInterface(firstModem()),
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.action("notifications.simunlock")
.string_attribute("x-canonical-type", "com.canonical.snapdecision.pinlock")
.string_attribute("x-canonical-pin-min-max", "notifications.pinMinMax")
.string_attribute("x-canonical-pin-popup", "notifications.popup")
.string_attribute("x-canonical-pin-error", "notifications.error")
.set_action_state(shared_ptr(g_variant_new_string("1234"), &mh::gvariant_deleter))
).match());
// check that the "EnterPin" method was called
// check method arguments are correct
WAIT_FOR_SIGNALS(modemSpy, 1);
CHECK_METHOD_CALL(modemSpy, 0, "EnterPin", {0, "pin"}, {1, "1234"});
modemSpy.clear();
// check that the "NotificationClosed" signal was emitted
WAIT_FOR_SIGNALS(notificationClosedSpy, 1);
EXPECT_EQ(notificationClosedSpy.first(), QVariantList() << QVariant(1) << QVariant(1));
notificationClosedSpy.clear();
// check that the "CloseNotification" method was called
// check method arguments are correct
WAIT_FOR_SIGNALS(notificationsSpy, 1);
CHECK_METHOD_CALL(notificationsSpy, 0, "CloseNotification", {0, "1"});
notificationsSpy.clear();
}
TEST_F(TestIndicator, UnlockSIM_IncorrectPin)
{
// set flight mode off, wifi off, and cell data off, and sim in
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// set sim locked
setSimManagerProperty(firstModem(), "PinRequired", "pin");
QSignalSpy notificationsSpy(¬ificationsMockInterface(),
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
// start the indicator
ASSERT_NO_THROW(startIndicator());
// check indicator is a locked sim card and a 0-bar wifi icon.
// check sim status shows “SIM Locked”, with locked sim card icon and a “Unlock SIM” button beneath.
// check that the “Unlock SIM” button has the correct action name.
// activate “Unlock SIM” action
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("", "SIM Locked", "simcard-locked", true)
.pass_through_activate("x-canonical-modem-locked-action")
)
.item(cellularSettings())
)
).match());
// check that the "GetServerInformation" method was called
// check that the "Notify" method was called twice
// check method arguments are correct
std::string busName;
WAIT_FOR_SIGNALS(notificationsSpy, 2);
CHECK_METHOD_CALL(notificationsSpy, 0, "GetServerInformation", /* no_args */);
CHECK_METHOD_CALL(notificationsSpy, 1, "Notify", {1, 0}, {3, "Enter SIM PIN"}, {4, "3 attempts remaining"});
{
QVariantList const& call(notificationsSpy.at(1));
QVariantList const& args(call.at(1).toList());
QVariantMap hints;
QVariantMap menuInfo;
ASSERT_TRUE(qDBusArgumentToMap(args.at(6), hints));
ASSERT_TRUE(qDBusArgumentToMap(hints["x-canonical-private-menu-model"], menuInfo));
busName = menuInfo["busName"].toString().toStdString();
}
notificationsSpy.clear();
// enter incorrect pin
// check that the notification is displaying no error message
QSignalSpy modemSpy(&modemMockInterface(firstModem()),
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "")
.set_action_state(shared_ptr(g_variant_new_string("4321"), &mh::gvariant_deleter))
).match());
// check that the "EnterPin" method was called
// check method arguments are correct
WAIT_FOR_SIGNALS(modemSpy, 1);
CHECK_METHOD_CALL(modemSpy, 0, "EnterPin", {0, "pin"}, {1, "4321"});
modemSpy.clear();
// check that the "Notify" method was called when retries changes, then again for incorrect pin
// check method arguments are correct (notification index should still be 1)
WAIT_FOR_SIGNALS(notificationsSpy, 2);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Enter SIM PIN"}, {4, "2 attempts remaining"});
CHECK_METHOD_CALL(notificationsSpy, 1, "Notify", {1, 1}, {3, "Enter SIM PIN"}, {4, "2 attempts remaining"});
notificationsSpy.clear();
// check that the notification is displaying the appropriate error message
// close the error message
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "Sorry, incorrect PIN")
.pass_through_activate("x-canonical-pin-error")
).match());
// check that the error message is no longer displayed
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "")
).match());
// enter incorrect pin again
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.set_action_state(shared_ptr(g_variant_new_string("4321"), &mh::gvariant_deleter))
).match());
// check that the "EnterPin" method was called
WAIT_FOR_SIGNALS(modemSpy, 1);
CHECK_METHOD_CALL(modemSpy, 0, "EnterPin", {0, "pin"}, {1, "4321"});
modemSpy.clear();
// check that the "Notify" method was called when retries changes, then again for incorrect pin
// check method arguments are correct (notification index should still be 1)
WAIT_FOR_SIGNALS(notificationsSpy, 2);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Enter SIM PIN"}, {4, "1 attempt remaining"});
CHECK_METHOD_CALL(notificationsSpy, 1, "Notify", {1, 1}, {3, "Enter SIM PIN"}, {4, "1 attempt remaining"});
notificationsSpy.clear();
// check that the error message and last attempt popup are displayed
// close the error and popup
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "Sorry, incorrect PIN")
.pass_through_string_attribute("x-canonical-pin-popup",
"Sorry, incorrect SIM PIN. This will be your last attempt. "
"If SIM PIN is entered incorrectly you will require your PUK code to unlock.")
.pass_through_activate("x-canonical-pin-error")
.pass_through_activate("x-canonical-pin-popup")
).match());
// check that the error and popup are no longer displayed
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "")
.pass_through_string_attribute("x-canonical-pin-popup", "")
).match());
// enter incorrect pin again
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.set_action_state(shared_ptr(g_variant_new_string("4321"), &mh::gvariant_deleter))
).match());
// check that the "EnterPin" method was called
WAIT_FOR_SIGNALS(modemSpy, 1);
CHECK_METHOD_CALL(modemSpy, 0, "EnterPin", {0, "pin"}, {1, "4321"});
modemSpy.clear();
// check that the "Notify" method was called when retries changes, then again for incorrect pin
// check method arguments are correct (notification index should still be 1)
WAIT_FOR_SIGNALS(notificationsSpy, 2);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Enter SIM PIN"}, {4, "0 attempts remaining"});
CHECK_METHOD_CALL(notificationsSpy, 1, "Notify", {1, 1}, {3, "Enter SIM PIN"}, {4, "0 attempts remaining"});
notificationsSpy.clear();
// set sim blocked
setSimManagerProperty(firstModem(), "PinRequired", "puk");
// clear the "SetProperty" method call
WAIT_FOR_SIGNALS(modemSpy, 1);
modemSpy.clear();
// check that the "Notify" method was called
// check method arguments are correct (notification index should still be 1)
WAIT_FOR_SIGNALS(notificationsSpy, 1);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Enter PUK code"}, {4, "10 attempts remaining"});
notificationsSpy.clear();
// check that the error message and last attempt popup are displayed
// close the error and popup
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "Sorry, incorrect PIN")
.pass_through_string_attribute("x-canonical-pin-popup",
"Sorry, your SIM is now blocked. Please enter your PUK code to unblock SIM card. "
"You may need to contact your network provider for PUK code.")
.pass_through_activate("x-canonical-pin-error")
.pass_through_activate("x-canonical-pin-popup")
).match());
// check that the error and popup are no longer displayed
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "")
.pass_through_string_attribute("x-canonical-pin-popup", "")
).match());
// enter incorrect puk
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.set_action_state(shared_ptr(g_variant_new_string("87654321"), &mh::gvariant_deleter))
).match());
// check that the "Notify" method was called
// check method arguments are correct (notification index should still be 1)
WAIT_FOR_SIGNALS(notificationsSpy, 1);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Enter new SIM PIN"}, {4, "Create new PIN"});
notificationsSpy.clear();
// enter new pin
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.set_action_state(shared_ptr(g_variant_new_string("4321"), &mh::gvariant_deleter))
).match());
// check that the "Notify" method was called
// check method arguments are correct (notification index should still be 1)
WAIT_FOR_SIGNALS(notificationsSpy, 1);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Confirm new SIM PIN"}, {4, "Create new PIN"});
notificationsSpy.clear();
// enter new pin again
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.set_action_state(shared_ptr(g_variant_new_string("4321"), &mh::gvariant_deleter))
).match());
// check that the "ResetPin" method was called
// check method arguments are correct
WAIT_FOR_SIGNALS(modemSpy, 1);
CHECK_METHOD_CALL(modemSpy, 0, "ResetPin", {0, "puk"}, {1, "87654321"}, {2, "4321"});
modemSpy.clear();
// check that the "Notify" method was called when retries changes, then again for incorrect pin
// check method arguments are correct (notification index should still be 1)
WAIT_FOR_SIGNALS(notificationsSpy, 2);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Confirm new SIM PIN"}, {4, "Create new PIN"});
CHECK_METHOD_CALL(notificationsSpy, 1, "Notify", {1, 1}, {3, "Enter PUK code"}, {4, "9 attempts remaining"});
notificationsSpy.clear();
// check that the notification is displaying the appropriate error message
// close the error message
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "Sorry, incorrect PUK")
.pass_through_activate("x-canonical-pin-error")
).match());
// check that the error message is no longer displayed
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "")
).match());
// enter correct puk
QSignalSpy notificationClosedSpy(&dbusMock.notificationDaemonInterface(),
SIGNAL(NotificationClosed(uint, uint)));
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.set_action_state(shared_ptr(g_variant_new_string("12345678"), &mh::gvariant_deleter))
).match());
// check that the "Notify" method was called
WAIT_FOR_SIGNALS(notificationsSpy, 1);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Enter new SIM PIN"}, {4, "Create new PIN"});
notificationsSpy.clear();
// enter new pin
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.set_action_state(shared_ptr(g_variant_new_string("4321"), &mh::gvariant_deleter))
).match());
// check that the "Notify" method was called
WAIT_FOR_SIGNALS(notificationsSpy, 1);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Confirm new SIM PIN"}, {4, "Create new PIN"});
notificationsSpy.clear();
// enter new pin again
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.set_action_state(shared_ptr(g_variant_new_string("4321"), &mh::gvariant_deleter))
).match());
// check that the "ResetPin" method was called
// check method arguments are correct
WAIT_FOR_SIGNALS(modemSpy, 1);
CHECK_METHOD_CALL(modemSpy, 0, "ResetPin", {0, "puk"}, {1, "12345678"}, {2, "4321"});
modemSpy.clear();
// check that the "NotificationClosed" signal was emitted
WAIT_FOR_SIGNALS(notificationClosedSpy, 1);
EXPECT_EQ(notificationClosedSpy.first(), QVariantList() << QVariant(1) << QVariant(1));
notificationClosedSpy.clear();
// check that the "Notify" method was called twice when retries changes
// check that the "CloseNotification" method was called
// check method arguments are correct
WAIT_FOR_SIGNALS(notificationsSpy, 2);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Confirm new SIM PIN"}, {4, "Create new PIN"});
CHECK_METHOD_CALL(notificationsSpy, 1, "CloseNotification", {0, "1"});
notificationsSpy.clear();
}
TEST_F(TestIndicator, UnlockSIM2_IncorrectPin)
{
// set flight mode off, wifi off, and cell data off, and sim in
setGlobalConnectedState(NM_STATE_DISCONNECTED);
// set sim locked
auto secondModem = createModem("ril_1");
setSimManagerProperty(secondModem, "PinRequired", "pin");
QSignalSpy notificationsSpy(¬ificationsMockInterface(),
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
// start the indicator
ASSERT_NO_THROW(startIndicator());
// check indicator is a locked sim card and a 0-bar wifi icon.
// check sim status shows “SIM Locked”, with locked sim card icon and a “Unlock SIM” button beneath.
// check that the “Unlock SIM” button has the correct action name.
// activate “Unlock SIM” action
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::starts_with)
.item(flightModeSwitch())
.item(mh::MenuItemMatcher()
.item(modemInfo("SIM 1", "fake.tel", "gsm-3g-full"))
.item(modemInfo("SIM 2", "SIM Locked", "simcard-locked", true)
.pass_through_activate("x-canonical-modem-locked-action")
)
.item(cellularSettings())
)
).match());
// check that the "GetServerInformation" method was called
// check that the "Notify" method was called twice
// check method arguments are correct
std::string busName;
WAIT_FOR_SIGNALS(notificationsSpy, 2);
CHECK_METHOD_CALL(notificationsSpy, 0, "GetServerInformation", /* no_args */);
CHECK_METHOD_CALL(notificationsSpy, 1, "Notify", {1, 0}, {3, "Enter SIM 2 PIN"}, {4, "3 attempts remaining"});
{
QVariantList const& call(notificationsSpy.at(1));
QVariantList const& args(call.at(1).toList());
QVariantMap hints;
QVariantMap menuInfo;
ASSERT_TRUE(qDBusArgumentToMap(args.at(6), hints));
ASSERT_TRUE(qDBusArgumentToMap(hints["x-canonical-private-menu-model"], menuInfo));
busName = menuInfo["busName"].toString().toStdString();
}
notificationsSpy.clear();
// enter incorrect pin
// check that the notification is displaying no error message
QSignalSpy modemSpy(&modemMockInterface(secondModem),
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "")
.set_action_state(shared_ptr(g_variant_new_string("4321"), &mh::gvariant_deleter))
).match());
// check that the "EnterPin" method was called
// check method arguments are correct
WAIT_FOR_SIGNALS(modemSpy, 1);
CHECK_METHOD_CALL(modemSpy, 0, "EnterPin", {0, "pin"}, {1, "4321"});
modemSpy.clear();
// check that the "Notify" method was called when retries changes, then again for incorrect pin
// check method arguments are correct (notification index should still be 1)
WAIT_FOR_SIGNALS(notificationsSpy, 2);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Enter SIM 2 PIN"}, {4, "2 attempts remaining"});
CHECK_METHOD_CALL(notificationsSpy, 1, "Notify", {1, 1}, {3, "Enter SIM 2 PIN"}, {4, "2 attempts remaining"});
notificationsSpy.clear();
// check that the notification is displaying the appropriate error message
// close the error message
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "Sorry, incorrect PIN")
.pass_through_activate("x-canonical-pin-error")
).match());
// check that the error message is no longer displayed
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "")
).match());
// enter incorrect pin again
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.set_action_state(shared_ptr(g_variant_new_string("4321"), &mh::gvariant_deleter))
).match());
// check that the "EnterPin" method was called
WAIT_FOR_SIGNALS(modemSpy, 1);
CHECK_METHOD_CALL(modemSpy, 0, "EnterPin", {0, "pin"}, {1, "4321"});
modemSpy.clear();
// check that the "Notify" method was called when retries changes, then again for incorrect pin
// check method arguments are correct (notification index should still be 1)
WAIT_FOR_SIGNALS(notificationsSpy, 2);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Enter SIM 2 PIN"}, {4, "1 attempt remaining"});
CHECK_METHOD_CALL(notificationsSpy, 1, "Notify", {1, 1}, {3, "Enter SIM 2 PIN"}, {4, "1 attempt remaining"});
notificationsSpy.clear();
// check that the error message and last attempt popup are displayed
// close the error and popup
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "Sorry, incorrect PIN")
.pass_through_string_attribute("x-canonical-pin-popup",
"Sorry, incorrect SIM 2 PIN. This will be your last attempt. "
"If SIM 2 PIN is entered incorrectly you will require your PUK code to unlock.")
.pass_through_activate("x-canonical-pin-error")
.pass_through_activate("x-canonical-pin-popup")
).match());
// check that the error and popup are no longer displayed
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "")
.pass_through_string_attribute("x-canonical-pin-popup", "")
).match());
// enter incorrect pin again
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.set_action_state(shared_ptr(g_variant_new_string("4321"), &mh::gvariant_deleter))
).match());
// check that the "EnterPin" method was called
WAIT_FOR_SIGNALS(modemSpy, 1);
CHECK_METHOD_CALL(modemSpy, 0, "EnterPin", {0, "pin"}, {1, "4321"});
modemSpy.clear();
// check that the "Notify" method was called when retries changes, then again for incorrect pin
// check method arguments are correct (notification index should still be 1)
WAIT_FOR_SIGNALS(notificationsSpy, 2);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Enter SIM 2 PIN"}, {4, "0 attempts remaining"});
CHECK_METHOD_CALL(notificationsSpy, 1, "Notify", {1, 1}, {3, "Enter SIM 2 PIN"}, {4, "0 attempts remaining"});
notificationsSpy.clear();
// set sim blocked
setSimManagerProperty(secondModem, "PinRequired", "puk");
// clear the "SetProperty" method call
WAIT_FOR_SIGNALS(modemSpy, 1);
modemSpy.clear();
// check that the "Notify" method was called
// check method arguments are correct (notification index should still be 1)
WAIT_FOR_SIGNALS(notificationsSpy, 1);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Enter PUK code for SIM 2"}, {4, "10 attempts remaining"});
notificationsSpy.clear();
// check that the error message and last attempt popup are displayed
// close the error and popup
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "Sorry, incorrect PIN")
.pass_through_string_attribute("x-canonical-pin-popup",
"Sorry, your SIM 2 is now blocked. Please enter your PUK code to unblock SIM card. "
"You may need to contact your network provider for PUK code.")
.pass_through_activate("x-canonical-pin-error")
.pass_through_activate("x-canonical-pin-popup")
).match());
// check that the error and popup are no longer displayed
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "")
.pass_through_string_attribute("x-canonical-pin-popup", "")
).match());
// enter incorrect puk
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.set_action_state(shared_ptr(g_variant_new_string("87654321"), &mh::gvariant_deleter))
).match());
// check that the "Notify" method was called
// check method arguments are correct (notification index should still be 1)
WAIT_FOR_SIGNALS(notificationsSpy, 1);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Enter new SIM 2 PIN"}, {4, "Create new PIN"});
notificationsSpy.clear();
// enter new pin
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.set_action_state(shared_ptr(g_variant_new_string("4321"), &mh::gvariant_deleter))
).match());
// check that the "Notify" method was called
// check method arguments are correct (notification index should still be 1)
WAIT_FOR_SIGNALS(notificationsSpy, 1);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Confirm new SIM 2 PIN"}, {4, "Create new PIN"});
notificationsSpy.clear();
// enter new pin again
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.set_action_state(shared_ptr(g_variant_new_string("4321"), &mh::gvariant_deleter))
).match());
// check that the "ResetPin" method was called
// check method arguments are correct
WAIT_FOR_SIGNALS(modemSpy, 1);
CHECK_METHOD_CALL(modemSpy, 0, "ResetPin", {0, "puk"}, {1, "87654321"}, {2, "4321"});
modemSpy.clear();
// check that the "Notify" method was called when retries changes, then again for incorrect pin
// check method arguments are correct (notification index should still be 1)
WAIT_FOR_SIGNALS(notificationsSpy, 2);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Confirm new SIM 2 PIN"}, {4, "Create new PIN"});
CHECK_METHOD_CALL(notificationsSpy, 1, "Notify", {1, 1}, {3, "Enter PUK code for SIM 2"}, {4, "9 attempts remaining"});
notificationsSpy.clear();
// check that the notification is displaying the appropriate error message
// close the error message
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "Sorry, incorrect PUK")
.pass_through_activate("x-canonical-pin-error")
).match());
// check that the error message is no longer displayed
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.pass_through_string_attribute("x-canonical-pin-error", "")
).match());
// enter correct puk
QSignalSpy notificationClosedSpy(&dbusMock.notificationDaemonInterface(),
SIGNAL(NotificationClosed(uint, uint)));
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.set_action_state(shared_ptr(g_variant_new_string("12345678"), &mh::gvariant_deleter))
).match());
// check that the "Notify" method was called
WAIT_FOR_SIGNALS(notificationsSpy, 1);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Enter new SIM 2 PIN"}, {4, "Create new PIN"});
notificationsSpy.clear();
// enter new pin
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.set_action_state(shared_ptr(g_variant_new_string("4321"), &mh::gvariant_deleter))
).match());
// check that the "Notify" method was called
WAIT_FOR_SIGNALS(notificationsSpy, 1);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Confirm new SIM 2 PIN"}, {4, "Create new PIN"});
notificationsSpy.clear();
// enter new pin again
EXPECT_MATCHRESULT(mh::MenuMatcher(unlockSimParameters(busName, 0))
.item(mh::MenuItemMatcher()
.set_action_state(shared_ptr(g_variant_new_string("4321"), &mh::gvariant_deleter))
).match());
// check that the "ResetPin" method was called
// check method arguments are correct
WAIT_FOR_SIGNALS(modemSpy, 1);
CHECK_METHOD_CALL(modemSpy, 0, "ResetPin", {0, "puk"}, {1, "12345678"}, {2, "4321"});
modemSpy.clear();
// check that the "NotificationClosed" signal was emitted
WAIT_FOR_SIGNALS(notificationClosedSpy, 1);
EXPECT_EQ(notificationClosedSpy.first(), QVariantList() << QVariant(1) << QVariant(1));
notificationClosedSpy.clear();
// check that the "Notify" method was called twice when retries changes
// check that the "CloseNotification" method was called
// check method arguments are correct
WAIT_FOR_SIGNALS(notificationsSpy, 2);
CHECK_METHOD_CALL(notificationsSpy, 0, "Notify", {1, 1}, {3, "Confirm new SIM 2 PIN"}, {4, "Create new PIN"});
CHECK_METHOD_CALL(notificationsSpy, 1, "CloseNotification", {0, "1"});
notificationsSpy.clear();
}
} // namespace
./tests/integration/test-connectivity-api-vpn.cpp 0000644 0000156 0000165 00000053150 12701153654 022341 0 ustar jenkins jenkins
/*
* Copyright (C) 2015 Canonical, Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
* Author: Pete Woods
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace testing;
using namespace connectivityqt;
typedef QPair> CS;
typedef QList CSL;
inline void PrintTo(const CS& list, std::ostream* os) {
QString output;
QDebug dbg(&output);
dbg << list;
*os << "CSL(" << output.toStdString() << ")";
}
namespace
{
class TestConnectivityApiVpn: public IndicatorNetworkTestBase
{
protected:
static void SetUpTestCase()
{
Connectivity::registerMetaTypes();
}
CSL vpnList(QAbstractItemModel& model)
{
CSL connectionStates;
int rowCount(model.rowCount());
for (int i = 0; i < rowCount; ++i)
{
auto idx = model.index(i, 0);
CS connectionState;
connectionState.first = model.data(idx, VpnConnectionsListModel::Roles::RoleId).toString();
connectionState.second << model.data(idx, VpnConnectionsListModel::Roles::RoleActive).toBool();
connectionState.second << model.data(idx, VpnConnectionsListModel::Roles::RoleActivatable).toBool();
connectionStates << connectionState;
}
return connectionStates;
}
unique_ptr getSortedVpnConnections(Connectivity& connectivity)
{
auto vpnConnections = connectivity.vpnConnections();
auto sortedVpnConnections = make_unique();
sortedVpnConnections->setSortRole(VpnConnectionsListModel::Roles::RoleId);
sortedVpnConnections->sort(0);
sortedVpnConnections->setSourceModel(vpnConnections);
return sortedVpnConnections;
}
OpenvpnConnection* getOpenvpnConnection(QAbstractItemModel* vpnConnections, int i)
{
return qobject_cast(
vpnConnections->data(
vpnConnections->index(i, 0),
VpnConnectionsListModel::Roles::RoleConnection).value<
QObject*>());
}
};
TEST_F(TestConnectivityApiVpn, VpnListStartsEmpty)
{
// Add a physical device to use for the connection
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
// Start the indicator
ASSERT_NO_THROW(startIndicator());
// Connect the the service
auto connectivity(newConnectivity());
auto sortedVpnConnections = getSortedVpnConnections(*connectivity);
QSignalSpy rowsAboutToBeRemovedSpy(sortedVpnConnections.get(), SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)));
QSignalSpy rowsRemovedSpy(sortedVpnConnections.get(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)));
QSignalSpy rowsAboutToBeInsertedSpy(sortedVpnConnections.get(), SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)));
QSignalSpy rowsInsertedSpy(sortedVpnConnections.get(), SIGNAL(rowsInserted(const QModelIndex &, int, int)));
QSignalSpy dataChangedSpy(sortedVpnConnections.get(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &, const QVector &)));
EXPECT_EQ(CSL(), vpnList(*sortedVpnConnections));
rowsAboutToBeRemovedSpy.clear();
rowsRemovedSpy.clear();
rowsAboutToBeInsertedSpy.clear();
rowsInsertedSpy.clear();
dataChangedSpy.clear();
// Add VPN configuration
auto appleConnection = createVpnConnection("apple");
WAIT_FOR_SIGNALS(rowsAboutToBeInsertedSpy, 1);
WAIT_FOR_SIGNALS(rowsInsertedSpy, 1);
EXPECT_TRUE(rowsAboutToBeRemovedSpy.isEmpty());
EXPECT_TRUE(rowsRemovedSpy.isEmpty());
EXPECT_TRUE(dataChangedSpy.isEmpty());
EXPECT_EQ(CSL({{"apple", {false, true}}}), vpnList(*sortedVpnConnections));
rowsAboutToBeRemovedSpy.clear();
rowsRemovedSpy.clear();
rowsAboutToBeInsertedSpy.clear();
rowsInsertedSpy.clear();
dataChangedSpy.clear();
// Delete the only VPN connection
deleteSettings(appleConnection);
WAIT_FOR_SIGNALS(rowsAboutToBeRemovedSpy, 1);
WAIT_FOR_SIGNALS(rowsRemovedSpy, 1);
EXPECT_TRUE(rowsAboutToBeInsertedSpy.isEmpty());
EXPECT_TRUE(rowsInsertedSpy.isEmpty());
EXPECT_TRUE(dataChangedSpy.isEmpty());
// List should be empty again
EXPECT_EQ(CSL(), vpnList(*sortedVpnConnections));
}
TEST_F(TestConnectivityApiVpn, VpnListStartsPopulated)
{
// Add VPN configurations
auto appleConnection = createVpnConnection("apple");
auto bananaConnection = createVpnConnection("banana");
auto coconutConnection = createVpnConnection("coconut");
// Add a physical device to use for the connection
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
// Start the indicator
ASSERT_NO_THROW(startIndicator());
// Connect the the service
auto connectivity(newConnectivity());
auto sortedVpnConnections = getSortedVpnConnections(*connectivity);
QSignalSpy rowsAboutToBeRemovedSpy(sortedVpnConnections.get(), SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)));
QSignalSpy rowsRemovedSpy(sortedVpnConnections.get(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)));
QSignalSpy rowsAboutToBeInsertedSpy(sortedVpnConnections.get(), SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)));
QSignalSpy rowsInsertedSpy(sortedVpnConnections.get(), SIGNAL(rowsInserted(const QModelIndex &, int, int)));
QSignalSpy dataChangedSpy(sortedVpnConnections.get(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &, const QVector &)));
EXPECT_EQ(CSL({{"apple", {false, true}}, {"banana", {false, true}}, {"coconut", {false, true}}}), vpnList(*sortedVpnConnections));
rowsAboutToBeRemovedSpy.clear();
rowsRemovedSpy.clear();
rowsAboutToBeInsertedSpy.clear();
rowsInsertedSpy.clear();
dataChangedSpy.clear();
// Delete a connection and check it is removed
deleteSettings(appleConnection);
WAIT_FOR_SIGNALS(rowsAboutToBeRemovedSpy, 1);
WAIT_FOR_SIGNALS(rowsRemovedSpy, 1);
EXPECT_TRUE(rowsAboutToBeInsertedSpy.isEmpty());
EXPECT_TRUE(rowsInsertedSpy.isEmpty());
EXPECT_TRUE(dataChangedSpy.isEmpty());
EXPECT_EQ(CSL({{"banana", {false, true}}, {"coconut", {false, true}}}), vpnList(*sortedVpnConnections));
rowsAboutToBeRemovedSpy.clear();
rowsRemovedSpy.clear();
rowsAboutToBeInsertedSpy.clear();
rowsInsertedSpy.clear();
dataChangedSpy.clear();
// Add a connection that should appear at the start
auto avocadoConnection = createVpnConnection("avocado");
EXPECT_TRUE(rowsAboutToBeRemovedSpy.isEmpty());
EXPECT_TRUE(rowsRemovedSpy.isEmpty());
WAIT_FOR_SIGNALS(rowsAboutToBeInsertedSpy, 1);
WAIT_FOR_SIGNALS(rowsInsertedSpy, 1);
EXPECT_TRUE(dataChangedSpy.isEmpty());
EXPECT_EQ(CSL({{"avocado", {false, true}}, {"banana", {false, true}}, {"coconut", {false, true}}}), vpnList(*sortedVpnConnections));
rowsAboutToBeRemovedSpy.clear();
rowsRemovedSpy.clear();
rowsAboutToBeInsertedSpy.clear();
rowsInsertedSpy.clear();
dataChangedSpy.clear();
// Activate the banana connection
auto activeConnection = createActiveConnection("0", device, bananaConnection, "/");
WAIT_FOR_SIGNALS(dataChangedSpy, 3);
EXPECT_TRUE(rowsAboutToBeRemovedSpy.isEmpty());
EXPECT_TRUE(rowsRemovedSpy.isEmpty());
EXPECT_TRUE(rowsAboutToBeInsertedSpy.isEmpty());
EXPECT_TRUE(rowsInsertedSpy.isEmpty());
EXPECT_EQ(CSL({{"avocado", {false, false}}, {"banana", {true, true}}, {"coconut", {false, false}}}), vpnList(*sortedVpnConnections));
rowsAboutToBeRemovedSpy.clear();
rowsRemovedSpy.clear();
rowsAboutToBeInsertedSpy.clear();
rowsInsertedSpy.clear();
dataChangedSpy.clear();
// Deactivate the banana connection
removeActiveConnection(device, activeConnection);
WAIT_FOR_SIGNALS(dataChangedSpy, 3);
EXPECT_TRUE(rowsAboutToBeRemovedSpy.isEmpty());
EXPECT_TRUE(rowsRemovedSpy.isEmpty());
EXPECT_TRUE(rowsAboutToBeInsertedSpy.isEmpty());
EXPECT_TRUE(rowsInsertedSpy.isEmpty());
EXPECT_EQ(CSL({{"avocado", {false, true}}, {"banana", {false, true}}, {"coconut", {false, true}}}), vpnList(*sortedVpnConnections));
}
TEST_F(TestConnectivityApiVpn, FollowsVpnState)
{
// Add a single VPN configuration
auto appleConnection = createVpnConnection("apple");
// Add a physical device to use for the connection
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
// Start the indicator
ASSERT_NO_THROW(startIndicator());
// Connect the the service
auto connectivity(newConnectivity());
auto sortedVpnConnections = getSortedVpnConnections(*connectivity);
QSignalSpy rowsAboutToBeRemovedSpy(sortedVpnConnections.get(), SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)));
QSignalSpy rowsRemovedSpy(sortedVpnConnections.get(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)));
QSignalSpy rowsAboutToBeInsertedSpy(sortedVpnConnections.get(), SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)));
QSignalSpy rowsInsertedSpy(sortedVpnConnections.get(), SIGNAL(rowsInserted(const QModelIndex &, int, int)));
QSignalSpy dataChangedSpy(sortedVpnConnections.get(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &, const QVector &)));
EXPECT_EQ(CSL({{"apple", {false, true}}}), vpnList(*sortedVpnConnections));
rowsAboutToBeRemovedSpy.clear();
rowsRemovedSpy.clear();
rowsAboutToBeInsertedSpy.clear();
rowsInsertedSpy.clear();
dataChangedSpy.clear();
OrgFreedesktopNetworkManagerSettingsConnectionInterface appleInterface(
NM_DBUS_SERVICE, appleConnection, dbusTestRunner.systemConnection());
QVariantDictMap settings = appleInterface.GetSettings();
settings["connection"]["id"] = "banana";
appleInterface.Update(settings).waitForFinished();
WAIT_FOR_SIGNALS(dataChangedSpy, 1);
EXPECT_TRUE(rowsAboutToBeRemovedSpy.isEmpty());
EXPECT_TRUE(rowsRemovedSpy.isEmpty());
EXPECT_TRUE(rowsAboutToBeInsertedSpy.isEmpty());
EXPECT_TRUE(rowsInsertedSpy.isEmpty());
// Name should have changed
EXPECT_EQ(CSL({{"banana", {false, true}}}), vpnList(*sortedVpnConnections));
}
TEST_F(TestConnectivityApiVpn, UpdatesVpnState)
{
// Add a single VPN configuration
auto appleConnection = createVpnConnection("apple");
// Add a physical device to use for the connection
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
// Start the indicator
ASSERT_NO_THROW(startIndicator());
// Connect the the service
auto connectivity(newConnectivity());
auto sortedVpnConnections = getSortedVpnConnections(*connectivity);
QSignalSpy rowsAboutToBeRemovedSpy(sortedVpnConnections.get(), SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)));
QSignalSpy rowsRemovedSpy(sortedVpnConnections.get(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)));
QSignalSpy rowsAboutToBeInsertedSpy(sortedVpnConnections.get(), SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)));
QSignalSpy rowsInsertedSpy(sortedVpnConnections.get(), SIGNAL(rowsInserted(const QModelIndex &, int, int)));
QSignalSpy dataChangedSpy(sortedVpnConnections.get(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &, const QVector &)));
EXPECT_EQ(CSL({{"apple", {false, true}}}), vpnList(*sortedVpnConnections));
rowsAboutToBeRemovedSpy.clear();
rowsRemovedSpy.clear();
rowsAboutToBeInsertedSpy.clear();
rowsInsertedSpy.clear();
dataChangedSpy.clear();
// Change the VPN connection's id
sortedVpnConnections->setData(
sortedVpnConnections->index(0, 0), "banana",
VpnConnectionsListModel::Roles::RoleId);
WAIT_FOR_SIGNALS(dataChangedSpy, 1);
EXPECT_TRUE(rowsAboutToBeRemovedSpy.isEmpty());
EXPECT_TRUE(rowsRemovedSpy.isEmpty());
EXPECT_TRUE(rowsAboutToBeInsertedSpy.isEmpty());
EXPECT_TRUE(rowsInsertedSpy.isEmpty());
// Name should have changed
EXPECT_EQ(CSL({{"banana", {false, true}}}), vpnList(*sortedVpnConnections));
OrgFreedesktopNetworkManagerSettingsConnectionInterface appleInterface(
NM_DBUS_SERVICE, appleConnection, dbusTestRunner.systemConnection());
QVariantDictMap settings = appleInterface.GetSettings();
EXPECT_EQ("banana", settings["connection"]["id"].toString());
rowsAboutToBeRemovedSpy.clear();
rowsRemovedSpy.clear();
rowsAboutToBeInsertedSpy.clear();
rowsInsertedSpy.clear();
dataChangedSpy.clear();
OrgFreedesktopNetworkManagerInterface managerInterface(
NM_DBUS_SERVICE, NM_DBUS_PATH,
dbusTestRunner.systemConnection());
QSignalSpy managerPropertiesSpy(&managerInterface, SIGNAL(PropertiesChanged(const QVariantMap &)));
// Activate the VPN connection
sortedVpnConnections->setData(
sortedVpnConnections->index(0, 0), true,
VpnConnectionsListModel::Roles::RoleActive);
WAIT_FOR_SIGNALS(dataChangedSpy, 1);
EXPECT_TRUE(rowsAboutToBeRemovedSpy.isEmpty());
EXPECT_TRUE(rowsRemovedSpy.isEmpty());
EXPECT_TRUE(rowsAboutToBeInsertedSpy.isEmpty());
EXPECT_TRUE(rowsInsertedSpy.isEmpty());
EXPECT_EQ(CSL({{"banana", {true, true}}}), vpnList(*sortedVpnConnections));
WAIT_FOR_SIGNALS(managerPropertiesSpy, 1);
auto activeConnections = managerInterface.activeConnections();
EXPECT_EQ(QList({QDBusObjectPath("/org/freedesktop/NetworkManager/ActiveConnection/0")}),
activeConnections);
}
TEST_F(TestConnectivityApiVpn, ReadsOpenvpnProperties)
{
// Add a single VPN configuration
auto appleConnection = createVpnConnection("apple", "org.freedesktop.NetworkManager.openvpn",
{
{"connection-type", "password-tls"},
{"remote", "remotey"},
{"ca", "/my/ca.crt"},
{"cert", "/my/cert.crt"},
{"cert-pass-flags", "1"},
{"key", "/my/key.key"},
{"password-flags", "1"}
},
{
{"cert-pass", "certificate password"},
{"password", "the password"}
});
// Add a physical device to use for the connection
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
// Start the indicator
ASSERT_NO_THROW(startIndicator());
// Connect the the service
auto connectivity(newConnectivity());
auto vpnConnections = connectivity->vpnConnections();
ASSERT_EQ(CSL({{"apple", {false, true}}}), vpnList(*vpnConnections));
auto connection = getOpenvpnConnection(vpnConnections, 0);
ASSERT_TRUE(connection);
EXPECT_EQ("apple", connection->id());
EXPECT_FALSE(connection->active());
EXPECT_EQ(VpnConnection::Type::OPENVPN, connection->type());
EXPECT_EQ(OpenvpnConnection::ConnectionType::PASSWORD_TLS, connection->connectionType());
EXPECT_EQ("remotey", connection->remote());
EXPECT_EQ("/my/ca.crt", connection->ca());
EXPECT_EQ("/my/cert.crt", connection->cert());
EXPECT_EQ("/my/key.key", connection->key());
QSignalSpy caChangedSpy(connection, SIGNAL(caChanged(const QString &)));
QSignalSpy certChangedSpy(connection, SIGNAL(certChanged(const QString &)));
QSignalSpy keyChangedSpy(connection, SIGNAL(keyChanged(const QString &)));
QSignalSpy remoteChangedSpy(connection, SIGNAL(remoteChanged(const QString &)));
OrgFreedesktopNetworkManagerSettingsConnectionInterface appleInterface(
NM_DBUS_SERVICE, appleConnection, dbusTestRunner.systemConnection());
QVariantDictMap settings = appleInterface.GetSettings();
settings["vpn"]["data"] = QVariant::fromValue(QStringMap(
{
{"connection-type", "password-tls"},
{"remote", "remote2"},
{"ca", "/my/ca2.crt"},
{"cert", "/my/cert2.crt"},
{"cert-pass-flags", "1"},
{"key", "/my/key2.key"},
{"password-flags", "1"},
}));
auto reply = appleInterface.Update(settings);
reply.waitForFinished();
if (reply.isError())
{
EXPECT_FALSE(reply.isError()) << reply.error().message().toStdString();
}
WAIT_FOR_SIGNALS(caChangedSpy, 1);
WAIT_FOR_SIGNALS(certChangedSpy, 1);
WAIT_FOR_SIGNALS(keyChangedSpy, 1);
WAIT_FOR_SIGNALS(remoteChangedSpy, 1);
EXPECT_EQ("remote2", connection->remote());
EXPECT_EQ("/my/ca2.crt", connection->ca());
EXPECT_EQ("/my/cert2.crt", connection->cert());
EXPECT_EQ("/my/key2.key", connection->key());
QSignalSpy certPassChangedSpy(connection, SIGNAL(certPassChanged(const QString&)));
QSignalSpy passwordChangedSpy(connection, SIGNAL(passwordChanged(const QString&)));
connection->updateSecrets();
WAIT_FOR_SIGNALS(certPassChangedSpy, 1);
WAIT_FOR_SIGNALS(passwordChangedSpy, 1);
EXPECT_EQ("certificate password", connection->certPass());
EXPECT_EQ("the password", connection->password());
}
TEST_F(TestConnectivityApiVpn, WritesOpenvpnProperties)
{
// Add a single VPN configuration
auto appleConnection = createVpnConnection("apple", "org.freedesktop.NetworkManager.openvpn",
{
{"connection-type", "tls"},
{"remote", "remotey"},
{"ca", "/my/ca.crt"},
{"cert", "/my/cert.crt"},
{"cert-pass-flags", "1"},
{"key", "/my/key.key"}
});
// Add a physical device to use for the connection
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
// Start the indicator
ASSERT_NO_THROW(startIndicator());
// Connect the the service
auto connectivity(newConnectivity());
auto vpnConnections = connectivity->vpnConnections();
ASSERT_EQ(CSL({{"apple", {false, true}}}), vpnList(*vpnConnections));
auto connection = getOpenvpnConnection(vpnConnections, 0);
ASSERT_TRUE(connection);
QSignalSpy remoteChangedSpy(connection, SIGNAL(remoteChanged(const QString &)));
OrgFreedesktopNetworkManagerSettingsConnectionInterface appleInterface(
NM_DBUS_SERVICE, appleConnection,
dbusTestRunner.systemConnection());
QSignalSpy appleInterfaceSpy(&appleInterface, SIGNAL(Updated()));
EXPECT_EQ("apple", connection->id());
EXPECT_FALSE(connection->active());
EXPECT_EQ(VpnConnection::Type::OPENVPN, connection->type());
EXPECT_EQ(OpenvpnConnection::ConnectionType::TLS, connection->connectionType());
connection->setRemote("remote2");
WAIT_FOR_SIGNALS(appleInterfaceSpy, 1);
WAIT_FOR_SIGNALS(remoteChangedSpy, 1);
QStringMap vpnData;
QVariantDictMap settings = appleInterface.GetSettings();
settings["vpn"]["data"].value() >> vpnData;
EXPECT_EQ("remote2", vpnData["remote"]);
}
TEST_F(TestConnectivityApiVpn, CreatesOpenvpnConnection)
{
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
// Start the indicator
ASSERT_NO_THROW(startIndicator());
// Connect the the service
auto connectivity(newConnectivity());
auto vpnConnections = qobject_cast(connectivity->vpnConnections());
ASSERT_TRUE(vpnConnections);
QSignalSpy addConnectionSpy(vpnConnections, SIGNAL(addFinished(VpnConnection *)));
vpnConnections->add(VpnConnection::Type::OPENVPN);
WAIT_FOR_SIGNALS(addConnectionSpy, 1);
ASSERT_EQ(CSL({{"VPN connection 1", {false, true}}}), vpnList(*vpnConnections));
auto connection = getOpenvpnConnection(vpnConnections, 0);
ASSERT_TRUE(connection);
// These should be the same object instance
EXPECT_EQ(addConnectionSpy.first().first().value(), connection);
}
TEST_F(TestConnectivityApiVpn, DeletesVpnConnection)
{
// Add a single VPN configuration
auto appleConnection = createVpnConnection("apple", "org.freedesktop.NetworkManager.openvpn",
{
{"connection-type", "tls"},
{"remote", "remotey"},
{"ca", "/my/ca.crt"},
{"cert", "/my/cert.crt"},
{"cert-pass-flags", "1"},
{"key", "/my/key.key"}
});
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
// Start the indicator
ASSERT_NO_THROW(startIndicator());
// Connect the the service
auto connectivity(newConnectivity());
auto vpnConnections = qobject_cast(connectivity->vpnConnections());
ASSERT_TRUE(vpnConnections);
ASSERT_EQ(CSL({{"apple", {false, true}}}), vpnList(*vpnConnections));
auto connection = getOpenvpnConnection(vpnConnections, 0);
ASSERT_TRUE(connection);
QSignalSpy rowsRemovedSpy(vpnConnections, SIGNAL(rowsRemoved(const QModelIndex &, int, int)));
vpnConnections->remove(connection);
WAIT_FOR_SIGNALS(rowsRemovedSpy, 1);
EXPECT_EQ(0, vpnConnections->rowCount(QModelIndex()));
}
}
./tests/integration/test-indicator-vpn.cpp 0000644 0000156 0000165 00000016461 12701153654 021034 0 ustar jenkins jenkins /*
* Copyright (C) 2015 Canonical, Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
* Author: Pete Woods
*/
#include
#include
#include
#include
using namespace std;
using namespace testing;
namespace mh = unity::gmenuharness;
namespace
{
class TestIndicatorVpn: public IndicatorNetworkTestBase
{
};
TEST_F(TestIndicatorVpn, ReadStateAtStartup)
{
// Add VPN configurations
auto appleConnection = createVpnConnection("apple");
auto bananaConnection = createVpnConnection("banana");
auto coconutConnection = createVpnConnection("coconut");
// Add a physical device to use for the connection
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
// Activate the banana connection
auto activeConnection = createActiveConnection("0", device, bananaConnection, "/");
ASSERT_NO_THROW(startIndicator());
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::all)
.submenu()
.item(flightModeSwitch())
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch())
.item(mh::MenuItemMatcher())
.item(wifiSettings())
.item(mh::MenuItemMatcher()
.section()
.item(vpnConnection("apple"))
.item(vpnConnection("banana", ConnectionStatus::connected))
.item(vpnConnection("coconut"))
.item(vpnSettings())
)
).match());
}
TEST_F(TestIndicatorVpn, FollowStateChanges)
{
// Add VPN configurations
auto appleConnection = createVpnConnection("apple");
auto bananaConnection = createVpnConnection("banana");
// Add a physical device to use for the connection
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
ASSERT_NO_THROW(startIndicator());
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::all)
.submenu()
.item(flightModeSwitch())
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch())
.item(mh::MenuItemMatcher())
.item(wifiSettings())
.item(mh::MenuItemMatcher()
.section()
.item(vpnConnection("apple"))
.item(vpnConnection("banana"))
.item(vpnSettings())
)
).match());
// Activate the apple connection
auto activeConnection = createActiveConnection("0", device, appleConnection, "/");
// Create another inactive connection
auto coconutConnection = createVpnConnection("coconut");
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::all)
.submenu()
.item(flightModeSwitch())
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch())
.item(mh::MenuItemMatcher())
.item(wifiSettings())
.item(mh::MenuItemMatcher()
.section()
.item(vpnConnection("apple", ConnectionStatus::connected))
.item(vpnConnection("banana"))
.item(vpnConnection("coconut"))
.item(vpnSettings())
)
).match());
}
TEST_F(TestIndicatorVpn, ActivatesConnection)
{
// Add VPN configurations
auto appleConnection = createVpnConnection("apple");
// Add a physical device to use for the connection
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
ASSERT_NO_THROW(startIndicator());
QSignalSpy networkManagerMockInterfaceSpy(&networkManagerMockInterface(),
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::all)
.submenu()
.item(flightModeSwitch())
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch())
.item(mh::MenuItemMatcher())
.item(wifiSettings())
.item(mh::MenuItemMatcher()
.section()
.item(vpnConnection("apple")
.activate()
)
.item(vpnSettings())
)
).match());
WAIT_FOR_SIGNALS(networkManagerMockInterfaceSpy, 1);
EXPECT_EQ(qVariantToString(
QVariantList()
<< QVariant("ActivateConnection")
<< QVariant(
QVariantList()
<< QVariant::fromValue(QDBusObjectPath(appleConnection))
<< QVariant::fromValue(QDBusObjectPath("/"))
<< QVariant::fromValue(QDBusObjectPath("/"))
)
),
qVariantToString(networkManagerMockInterfaceSpy.first())
);
}
TEST_F(TestIndicatorVpn, DeactivatesConnection)
{
// Add VPN configurations
auto appleConnection = createVpnConnection("apple");
// Add a physical device to use for the connection
setGlobalConnectedState(NM_STATE_CONNECTED_GLOBAL);
auto device = createWiFiDevice(NM_DEVICE_STATE_ACTIVATED);
// Activate the apple connection
auto activeConnection = createActiveConnection("0", device, appleConnection, "/");
ASSERT_NO_THROW(startIndicator());
QSignalSpy networkManagerMockInterfaceSpy(&networkManagerMockInterface(),
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
EXPECT_MATCHRESULT(mh::MenuMatcher(phoneParameters())
.item(mh::MenuItemMatcher()
.mode(mh::MenuItemMatcher::Mode::all)
.submenu()
.item(flightModeSwitch())
.item(mh::MenuItemMatcher())
.item(wifiEnableSwitch())
.item(mh::MenuItemMatcher())
.item(wifiSettings())
.item(mh::MenuItemMatcher()
.section()
.item(vpnConnection("apple", ConnectionStatus::connected)
.activate()
)
.item(vpnSettings())
)
).match());
WAIT_FOR_SIGNALS(networkManagerMockInterfaceSpy, 2);
EXPECT_EQ(qVariantToString(
QVariantList()
<< QVariant("DeactivateConnection")
<< QVariant(
QVariantList()
<< QVariant::fromValue(QDBusObjectPath(activeConnection))
)
),
qVariantToString(networkManagerMockInterfaceSpy.first())
);
}
} // namespace
./tests/integration/CMakeLists.txt 0000644 0000156 0000165 00000001521 12701153654 017325 0 ustar jenkins jenkins
add_definitions(-DNETWORK_SERVICE_BIN="${CMAKE_BINARY_DIR}/src/indicator/indicator-network-service")
include_directories(
"${CMAKE_SOURCE_DIR}/src/connectivity-api/connectivity-qt"
"${CMAKE_SOURCE_DIR}/src/qdbus-stubs"
"${CMAKE_BINARY_DIR}/src/qdbus-stubs"
)
set(
INTEGRATION_TESTS_SRC
indicator-network-test-base.cpp
test-indicator.cpp
test-indicator-vpn.cpp
test-connectivity-api.cpp
test-connectivity-api-vpn.cpp
)
add_executable(
integration-tests
${INTEGRATION_TESTS_SRC}
)
qt5_use_modules(
integration-tests
Core
DBus
Test
)
target_link_libraries(
integration-tests
test-utils
${CONNECTIVITY_QT_LIB_TARGET}
${TEST_DEPENDENCIES_LDFLAGS}
${GTEST_LIBRARIES}
${GMOCK_LIBRARIES}
${GLIB_LDFLAGS}
)
add_test(
integration-tests
integration-tests
)
./tests/utils/ 0000755 0000156 0000165 00000000000 12701153654 013403 5 ustar jenkins jenkins ./tests/utils/main.cpp 0000644 0000156 0000165 00000002747 12701153654 015045 0 ustar jenkins jenkins /*
* Copyright © 2014 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
* Authors:
* Pete Woods
*/
#include
#include
#include
#include
#include
using namespace QtDBusMock;
class Runner: public QObject
{
Q_OBJECT
public Q_SLOTS:
void run()
{
QCoreApplication::exit(RUN_ALL_TESTS());
}
};
int main(int argc, char **argv)
{
qputenv("LANG", "C.UTF-8");
unsetenv("LC_ALL");
unsetenv("GDM_LANG");
unsetenv("LANGUAGE");
setlocale(LC_ALL, "");
bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR);
textdomain(GETTEXT_PACKAGE);
QCoreApplication application(argc, argv);
DBusMock::registerMetaTypes();
::testing::InitGoogleTest(&argc, argv);
Runner runner;
QTimer::singleShot(0, &runner, SLOT(run()));
return application.exec();
}
#include "main.moc"
./tests/utils/action-utils.cpp 0000644 0000156 0000165 00000003661 12701153654 016530 0 ustar jenkins jenkins /*
* Copyright © 2014 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
* Authors:
* Pete Woods
*/
#include
using namespace std;
QString
testutils::string_value (MenuItem::Ptr menuItem, const QString &name)
{
char *attribute = NULL;
if (g_menu_item_get_attribute(menuItem->gmenuitem(), name.toUtf8().constData(), "s",
&attribute))
{
QString result = QString::fromUtf8(attribute);
g_free(attribute);
return result;
}
throw std::logic_error("could not get string attribute");
}
bool
testutils::bool_value (MenuItem::Ptr menuItem, const QString &name)
{
gboolean result;
if (!g_menu_item_get_attribute(menuItem->gmenuitem(), name.toUtf8().constData(), "b",
&result))
{
throw std::logic_error("could not get boolean attribute");
}
return (result == TRUE);
}
Action::Ptr
testutils::findAction (ActionGroup::Ptr actionGroup, const QString &name)
{
auto pos = name.indexOf('.');
QString shortName = name.mid(pos + 1);
::Action::Ptr action;
std::set< ::Action::Ptr> actions = actionGroup->actions();
for (auto it(actions.begin()); it != actions.end(); ++it)
{
if ((*it)->name() == shortName)
{
action = *it;
}
}
return action;
}
./tests/utils/action-utils.h 0000644 0000156 0000165 00000002072 12701153654 016170 0 ustar jenkins jenkins /*
* Copyright © 2014 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
* Authors:
* Pete Woods
*/
#pragma once
#include
#include
#include
namespace testutils
{
QString
string_value (MenuItem::Ptr menuItem, const QString &name);
bool
bool_value (MenuItem::Ptr menuItem, const QString &name);
Action::Ptr
findAction (ActionGroup::Ptr actionGroup, const QString &name);
} /* namespace testutils */
./tests/utils/CMakeLists.txt 0000644 0000156 0000165 00000000250 12701153654 016140 0 ustar jenkins jenkins
include_directories("${CMAKE_SOURCE_DIR}/src")
add_library(
test-utils
STATIC
main.cpp
action-utils.cpp
)
qt5_use_modules(
test-utils
Core
)
./tests/data/ 0000755 0000156 0000165 00000000000 12701153654 013154 5 ustar jenkins jenkins ./tests/data/phonesim/ 0000755 0000156 0000165 00000000000 12701153654 014776 5 ustar jenkins jenkins ./tests/data/phonesim/pin-unlock.xml 0000644 0000156 0000165 00000301420 12701153654 017577 0 ustar jenkins jenkins
AT+CGMI
${GMI}\n\nOK
AT+CGMI=?
OK
AT+GMI
${GMI}\n\nOK
AT+CGMM
${GMM}\n\nOK
AT+GMM
${GMM}\n\nOK
AT+CGMM=?
OK
AT+CGMR
${GMR}\n\nOK
AT+GMR
${GMR}\n\nOK
AT+CGMR=?
OK
AT+CGSN
${GSN}\n\nOK
AT+CGSN=?
OK
AT+GSN
${GSN}\n\nOK
AT+CIMI
${IMSI}\n\nOK
AT+CIMI=?
OK
AT+CSCS?
+CSCS: "${SCS}"\n\nOK
AT+CSCS=?
+CSCS: "GSM","IRA","PCCP437","PCDN","8859-1","HEX","UCS2"\n\nOK
AT+CSCS="*"
OK
AT+WS46?
12\n\nOK
AT+WS46=?
(12)\n\nOK
AT+WS46=12
OK
AT+CSTA?
${STA}\n\nOK
AT+CSTA=?
(129, 145)\n\nOK
AT+CSTA=129
OK
AT+CSTA=145
OK
AT+CBST?
+CBST: 0\n\nOK
AT+CBST=?
+CBST: (0),(0),(0)\n\nOK
AT+CBST=*
OK
AT+CRLP?
+CRLP: 61,61,48,6\n\nOK
AT+CRLP=?
+CRLP: (61),(61),(48),(6)\n\nOK
AT+CRLP=*
OK
AT+CR?
+CR: ${CR}\n\nOK
AT+CR=?
+CR: (0,1)\n\nOK
AT+CR=0
OK
AT+CR=1
OK
AT+CEER
+CEER: ${ERR}\n\nOK
AT+CRC?
+CRC: ${CRC}\n\nOK
AT+CRC=?
+CRC: (0,1)\n\nOK
AT+CRC=0
OK
AT+CRC=1
OK
AT*ECAM?
*ECAM: ${ECAM}\n\nOK
AT*ECAM=?
*ECAM: (0,1)\n\nOK
AT*ECAM=0
OK
AT*ECAM=1
OK
AT+CNUM
+CNUM: ,"+358501234567",145,,4\n\nOK
AT+CNUM=?
OK
AT+CREG?
+CREG: ${REG},1\n\nOK
AT+CREG=?
+CREG: (0,1,2)\n\nOK
AT+CREG=*
OK
AT+CGREG?
+CGREG: ${GREG},1\n\nOK
AT+CGREG=?
+CGREG: (0,1,2)\n\nOK
AT+CGREG=*
OK
AT+COPN
+COPN: ${OP1PLMN},"${OP1}"\n+COPN: ${OP2PLMN},"${OP2}"\n+COPN: ${OP3PLMN},"${OP3}"\n+COPN: ${OP4PLMN},"${OP4}"\n+COPN: ${OP5PLMN},"${OP5}"\n+COPN: ${OP6PLMN},"${OP6}"\n+COPN: ${OP7PLMN},"${OP7}"\n+COPN: ${OP8PLMN},"${OP8}"\n+COPN: ${OP9PLMN},"${OP9}"\n+COPN: ${OP10PLMN},"${OP10}"\n+COPN: ${OP11PLMN},"${OP11}"\n\nOK
AT+COPS?
+COPS: ${OPMODE},${OPFORMAT},${OPDATA}\n\nOK
AT+COPS=3,2;+COPS?;+COPS=3,0;+COPS?
+COPS: 0,2,"${OPPLMN}"\n+COPS: 0,0,"${OP}"\n\nOK
AT+COPS=?
+COPS: (${OP1STATE},"${OP1}","TTAU","${OP1PLMN}",2),(${OP2STATE},"${OP2}","MFN","${OP2PLMN}",0),(${OP2STATE},"${OP2}","MFN","${OP2PLMN}",2),(${OP3STATE},"${OP3}","CNT","${OP3PLMN}"),(${OP4STATE},"${OP4}","BNT","${OP4PLMN}"),(${OP5STATE},"${OP5}","INT","${OP5PLMN}"),(${OP6STATE},"${OP6}","PNT","${OP6PLMN}"),(${OP7STATE},"${OP7}","TNT","${OP7PLMN}"),(${OP8STATE},"${OP8}","MNT","${OP8PLMN}"),(${OP9STATE},"${OP9}","IMSI","${OP9PLMN}"),(${OP10STATE},"${OP10}","NOT","${OP10PLMN}"),(${OP11STATE},"${OP11}","SER","${OP11PLMN}"),(${OP1STATE},"${OP1}","TTAU","${OP1PLMN}",0)\n\nOK
AT+COPS=3,0
OK
AT+COPS=3,2
OK
AT+COPS=0*
OK
AT+COPS=1,0,"${OP1}"
OK
AT+COPS=1,2,"${OP1PLMN}"
OK
AT+COPS=1,0,${OP2}
ERROR
AT+COPS=1,0,${OP3}
ERROR
AT+COPS=1,0,${OP4}
ERROR
AT+COPS=1,2,${OP2PLMN}
ERROR
AT+COPS=1,2,${OP3PLMN}
ERROR
AT+COPS=1,2,${OP4PLMN}
ERROR
AT+COPS=1,0,"${OP6}"
OK
AT+COPS=1,2,"${OP6PLMN}"
OK
AT+COPS=1,0,"${OP7}"
OK
AT+COPS=1,2,"${OP7PLMN}"
OK
AT+COPS=1,0,"${OP8}"
OK
AT+COPS=1,2,"${OP8PLMN}"
OK
AT+COPS=1,0,"${OP9}"
+CMS ERROR: 30
AT+COPS=1,2,${OP9PLMN}
+CMS ERROR: 30
AT+COPS=1,0,"${OP10}"
+CME ERROR: 32
AT+COPS=1,2,${OP10PLMN}
+CME ERROR: 32
AT+COPS=1,0,"${OP11}"
+CME ERROR: 30
AT+COPS=1,2,${OP11PLMN}
+CME ERROR: 30
AT+CPLS?
+CPLS: 0\n\nOK -->
AT+CPOL?
+CPOL: ${PO1}\n+CPOL: ${PO2}\n\nOK
AT+CPOL=1,2,*
OK
AT+CPOL=1
OK
AT+CPOL=2,2,*
OK
AT+CPOL=2
OK
AT+CPOL=3,2,*
OK
AT+CPOL=3
OK
AT+CPOL=4,2,*
OK
AT+CPOL=4
OK
AT+CPOL=5,2,*
OK
AT+CPOL=5
OK
AT+CPOL=6,2,*
OK
AT+CPOL=6
OK
AT+CPOL=7,2,*
OK
AT+CPOL=7
OK
AT+CPOL=8,2,*
OK
AT+CPOL=8
OK
AT+CLCK="AO",1,"${PIN2VALUE}",1
OK
AT+CLCK="AO",2
+CLCK: ${BARVAO},1\n\nOK
AT+CLCK="OI",1,"${PIN2VALUE}",1
OK
AT+CLCK="OI",2
+CLCK: ${BARVOI},1\n\nOK
AT+CLCK="OX",1,"${PIN2VALUE}",1
OK
AT+CLCK="OX",2
+CLCK: ${BARVOX},1\n\nOK
AT+CLCK="AI",1,"${PIN2VALUE}",1
OK
AT+CLCK="AI",2
+CLCK: ${BARVAI},1\n\nOK
AT+CLCK="IR",1,"${PIN2VALUE}",1
OK
AT+CLCK="IR",2
+CLCK: ${BARVIR},1\n\nOK
AT+CLCK="NT",1,"${PIN2VALUE}",1
OK
AT+CLCK="NT",2
+CLCK: ${BARVNT},7\n\nOK
AT+CLCK="NM",1,"${PIN2VALUE}",1
OK
AT+CLCK="NM",2
+CLCK: ${BARVNM},7\n\nOK
AT+CLCK="NS",1,"${PIN2VALUE}",1
OK
AT+CLCK="NS",2
+CLCK: ${BARVNS},7\n\nOK
AT+CLCK="NA",1,"${PIN2VALUE}",1
OK
AT+CLCK="NA",2
+CLCK: ${BARVNA},7\n\nOK
AT+CLCK="AB",0,"${PIN2VALUE}"
OK
AT+CLCK="AG",0,"${PIN2VALUE}",1
OK
AT+CLCK="AC",0,"${PIN2VALUE}",1
OK
AT+CLCK=?
+CLCK: PS(8),SC(8)\n\nOK
AT+CLCK="FD",2
+CLCK: ${FD}\n\nOK
AT+CLCK="FD",0,"${PIN2VALUE}"
OK
AT+CLCK="FD",1,"${PIN2VALUE}"
OK
AT+CLCK="FD",*
ERROR
AT+CLCK="SC",2
+CLCK: ${SC}\n\nOK
AT+CLCK="SC",0,"${PINVALUE}"
OK
AT+CLCK="SC",1,"${PINVALUE}"
OK
AT+CLCK="SC",*
ERROR
AT+CLCK="PS",2
+CLCK: ${PS}\n\nOK
AT+CLCK="PS",0,"${PSPINVALUE}"
OK
AT+CLCK="PS",1,"${PSPINVALUE}"
OK
AT+CLCK="PS",*
ERROR
AT+CPWD="PS","${PSPINVALUE}","*"
OK
AT+CPWD="AB","${PIN2VALUE}","*"
OK
AT+CPWD="AO","${PIN2VALUE}","*"
OK
AT+CPWD="OI","${PIN2VALUE}","*"
OK
AT+CPWD="OX","${PIN2VALUE}","*"
OK
AT+CPWD="AI","${PIN2VALUE}","*"
OK
AT+CPWD="IR","${PIN2VALUE}","*"
OK
AT+CPWD="NT","${PIN2VALUE}","*"
OK
AT+CPWD="NM","${PIN2VALUE}","*"
OK
AT+CPWD="NS","${PIN2VALUE}","*"
OK
AT+CPWD="NA","${PIN2VALUE}","*"
OK
AT+CLIP?
+CLIP: ${LIP},1\n\nOK
AT+CLIP=?
+CLIP: (0,1)\n\nOK
AT+CLIP=*
OK
AT+CDIP?
+CDIP: ${DIP},1\n\nOK
AT+CDIP=?
+CDIP: (0,1)\n\nOK
AT+CDIP=*
OK
AT+CNAP?
+CNAP: ${NAP},1\n\nOK
AT+CNAP=?
+CNAP: (0,1)\n\nOK
AT+CNAP=*
OK
AT+CLIR?
+CLIR: ${LIR},${LIR_STATUS}\n\nOK
AT+CLIR=?
+CLIR: (0,1,2)\n\nOK
AT+CLIR=*
OK
AT+COLP?
+COLP: ${OLP},1\n\nOK
AT+COLP=?
+COLP: (0,1)\n\nOK
AT+COLP=*
OK
AT+COLR
+COLR: 1\n\nOK
AT+COLR=?
OK
AT+CCUG?
+CCUG: 0,0,0\n\nOK
AT+CCUG*
OK
AT+CCFC=?
+CCFC: (0,1,2,3,4,5)\n\nOK
AT+CCFC=2,3,*,145,1,,,20
OK
AT+CCFC=2,3,*,129,1,,,20
OK
AT+CCFC=2,3,*,145,1,,,30
OK
AT+CCFC=2,3,*,129,1,,,30
OK
AT+CCFC=3,3,*,145,1
OK
AT+CCFC=3,3,*,129,1
OK
AT+CCFC=0,3,*,145,1
OK
AT+CCFC=0,3,*,129,1
OK
AT+CCFC=1,3,*,145,1
OK
AT+CCFC=1,3,*,129,1
OK
AT+CCFC=4,4
OK
AT+CCFC=5,4
OK
AT+CCFC=0,4
OK
AT+CCFC=0,4,,,1
OK
AT+CCFC=0,4,,,2
OK
AT+CCFC=0,4,,,4
OK
AT+CCFC=0,4,,,8
OK
AT+CCFC=1,4
OK
AT+CCFC=1,4,,,1
OK
AT+CCFC=1,4,,,2
OK
AT+CCFC=1,4,,,4
OK
AT+CCFC=1,4,,,8
OK
AT+CCFC=2,4
OK
AT+CCFC=2,4,,,1
OK
AT+CCFC=2,4,,,2
OK
AT+CCFC=2,4,,,4
OK
AT+CCFC=2,4,,,8
OK
AT+CCFC=3,4
OK
AT+CCFC=3,4,,,1
OK
AT+CCFC=3,4,,,2
OK
AT+CCFC=3,4,,,4
OK
AT+CCFC=3,4,,,8
OK
AT+CCFC=0,2
+CCFC: ${CF0C1},1,${CF0C1N},${CF0C1T}\n+CCFC: ${CF0C2},2,${CF0C2N}\n+CCFC: ${CF0C4},4,${CF0C4N}\n+CCFC: ${CF0C8},8,${CF0C8N}\n\nOK
AT+CCFC=1,2
+CCFC: ${CF1C1},1,${CF1C1N},${CF1C1T}\n+CCFC: ${CF1C2},2,${CF1C2N}\n+CCFC: ${CF1C4},4,${CF1C4N}\n+CCFC: ${CF1C8},8,${CF1C8N}\n\nOK
AT+CCFC=2,2
+CCFC: ${CF2C1},1,${CF2C1N},${CF2C1T},,,${CF2C1O}\n+CCFC: ${CF2C2},2,${CF2C2N}\n+CCFC: ${CF2C4},4,${CF2C4N}\n+CCFC: ${CF2C8},8,${CF2C8N}\n\nOK
AT+CCFC=3,2
+CCFC: ${CF3C1},1,${CF3C1N},${CF3C1T}\n+CCFC: ${CF3C2},2,${CF3C2N}\n+CCFC: ${CF3C4},4,${CF3C4N}\n+CCFC: ${CF3C8},8,${CF3C8N}\n\nOK
AT+CCWA?
+CCWA: 1\n\nOK
AT+CCWA=1,2
+CCWA: ${CWA_V},1\n+CCWA: ${CWA_D},2\n+CCWA: ${CWA_F},4\n\nOK
AT+CCWA=1,2,7
+CCWA: ${CWA_V},1\n+CCWA: ${CWA_D},2\n+CCWA: ${CWA_F},4\n\nOK
AT+CCWA=1,2,1
+CCWA: ${CWA_V},1\n\nOK
AT+CCWA=1,2,2
+CCWA: ${CWA_D},2\n\nOK
AT+CCWA=1,2,4
+CCWA: ${CWA_F},4\n\nOK
AT+CCWA=1,2,3
+CCWA: ${CWA_V},1\n+CCWA: ${CWA_D},2\n\nOK
AT+CCWA=1,2,5
+CCWA: ${CWA_V},1\n+CCWA: ${CWA_F},4\n\nOK
AT+CCWA=1,2,6
+CCWA: ${CWA_D},2\n+CCWA: ${CWA_F},4\n\nOK
AT+CCWA=?
+CCWA: (0,1)\n\nOK
AT+CCWA=1
OK
AT+CCWA=1,0,1OK
AT+CCWA=1,0,2OK
AT+CCWA=1,0,3OK
AT+CCWA=1,0,4OK
AT+CCWA=1,0,5OK
AT+CCWA=1,0,6OK
AT+CCWA=1,0,7OK
AT+CCWA=1,1,1OK
AT+CCWA=1,1,2OK
AT+CCWA=1,1,3OK
AT+CCWA=1,1,4OK
AT+CCWA=1,1,5OK
AT+CCWA=1,1,6OK
AT+CCWA=1,1,7OK
AT+CUSD?
+CUSD: ${USD}\n\nOK
AT+CUSD=?
+CUSD: (0,1)\n\nOK
AT+CUSD=1,"*225#",15
+CUSD: 0,"Thank you, your request is being processed. A message will be sent to your phone.",15\n\nOK
AT+CUSD=1,"response",15
+CUSD: 0,"Thank you.",15\n\nOK
AT+CUSD=1,"ABCD",240
+CUSD: 0,"USSD string received from SS",240\n\nOK
AT+CUSD=1,"41424344",68
+CUSD: 0,"5553534420737472696E672072656365697665642066726F6D205353",68\n\nOK
AT+CUSD=1,"041704140420041004120421042204120423041904220415",72
+CUSD: 0,"005500530053004400200073007400720069006E0067002000720065006300650069007600650064002000660072006F006D002000530053",72\n\nOK
AT+CUSD=1,"*123#",15
+CUSD: 4\n\nOK
AT+CUSD=1,*
OK
AT+CUSD=2
OK
AT+CUSD=1
OK
AT+CUSD=0
OK
AT+CAOC=0
+CAOC: "${AOC}"\n\nOK
AT+CAOC=*
OK
AT+CAOC?
+CAOC: ${AOCMODE}\n\nOK
AT+CAOC=?
+CAOC: (0-2)\n\nOK
AT+CACM="${SIMPIN2VALUE}"
OK
AT+CACM?
+CACM: "${ACM}"\n\nOK
AT+CACM=?
OK
AT+CAMM="*","${SIMPIN2VALUE}"
OK
AT+CAMM?
+CAMM: "${ACMMAX}"\n\nOK
AT+CAMM=?
OK
AT+CPUC="*","${SIMPIN2VALUE}"
OK
AT+CPUC?
+CPUC: "${PPU}"\n\nOK
AT+CPUC=?
OK
AT+CCWE=*
OK
AT+CCWE?
+CCWE: ${CWEMODE}\n\nOK
AT+CCWE=?
+CCWE: (0,1)\n\nOK
AT+CSSN?
+CSSN: ${SSN}\n\nOK
AT+CSSN=?
+CSSN: (0,1),(0,1)\n\nOK
AT+CSSN=*
OK
AT+CPAS
+CPAS: ${PAS}\n\nOK
AT+CPAS=?
+CPAS: (0-5)\n\nOK
AT+CFUN?
+CFUN: ${FUN}\n\nOK
AT+CFUN=?
+CFUN: (1,4)\n\nOK
AT+CFUN=1
OK
AT+CFUN=4
OK\n\n+CREG: 0\n\n+CGREG: 0
AT+CSMS=?
+CSMS=(0)\n\nOK
AT+CSMS?
+CSMS: 0,1,1,1\n\nOK
AT+CSMS=0
+CSMS: 1,1,1\n\nOK
AT+CSCA=?
OK
AT+CSCA?
+CSCA: "${SCA}",${SCAT}\n\nOK
AT+CSCA="*",145
OK
AT+CSCA="*",129
OK
AT+CPINR=?
OK\n
AT+CPINR
+CPINR: SIM PIN,${PINRETRYCOUNT},3\nOK\n
AT+CPIN?
+CPIN: ${PINNAME}\n\nOK
AT+CPIN="${PINVALUE}"
+CPIN: READY\n\nOK
AT+CPWD="P2","${PIN2VALUE}","*"
OK
AT+CPIN="${PUKVALUE}","*"
+CPIN: READY\n\nOK
AT+CPIN="${PUK2VALUE}","*"
+CPIN: READY\n\nOK
AT+CPIN="*","*"
+CPIN: SIM PUK\n\nERROR
AT+CPIN=*
+CPIN: SIM PIN\n\nERROR
AT+CPIN="${PINVALUE}"
+CPIN: READY\n\nOK
AT+CPIN="${PUKVALUE}","*"
+CPIN: READY\n\nOK
AT+CPIN=*
+CPIN: SIM PIN\n\nERROR
AT+CPIN="${PINVALUE}"
+CPIN: READY\n\nOK
AT+CPIN="${PUKVALUE}","*"
+CPIN: READY\n\nOK
AT+CPIN=*
+CPIN: SIM PUK\n\nERROR
AT+CBC
+CBC: ${BC}\n\nOK
AT+CBC=?
+CBC: (0,1,2,3),(1-100)\n\nOK
AT+CCED=1,8
OK\n+CSQ: ${SQ}
AT+CSQ
+CSQ: ${SQ}\n\nOK
AT+CSQ=?
+CSQ: (0-31,99),(0-7,99)\n\nOK
AT+CMEC?
+CMEC: ${MEC}\n\nOK
AT+CMEC=?
+CMEC: (0-2),(0-2),(0-2)\n\nOK
AT+CMEC=*
OK
AT+CKPD=*
OK
AT+CDIS*
OK
AT+CIND=?
+CIND: ("signal",(0-5)),("service",(0-1))\n\nOK
AT+CMER?
+CMER: ${MER}\n\nOK
AT+CMER=?
+CMER: (0-3),(0-2),(0-2),(0-2),(0-1)\n\nOK
AT+CMER=*
OK
AT+CCLK*
OK
AT+CALA*
OK
AT+CSIM*
ERROR
AT*TBAND?
*TBAND: ${BAND}\n\nOK
AT*TBAND=?
*TBAND: "${BAND0}"\n*TBAND: "${BAND1}"\n*TBAND: "${BAND2}"\n*TBAND: "${BAND3}"\n*TBAND: "${BAND4}"\n*TBAND: "${BAND5}"\n*TBAND: "${BAND6}"\n*TBAND: "${BAND7}"\n*TBAND: "${BAND8}"\n*TBAND: "${BAND9}"\n*TBAND: "${BANDA}"\n*TBAND: "${BANDB}"\n*TBAND: "${BANDC}"\n*TBAND: "${BANDD}"\n*TBAND: "${BANDE}"\n*TBAND: "${BANDF}"\n\nOK
AT*TBAND=0
OK
AT*TBAND=1,""
ERROR
AT*TBAND=1,"${BAND0}"
OK
AT*TBAND=1,"${BAND1}"
OK
AT*TBAND=1,"${BAND2}"
OK
AT*TBAND=1,"${BAND3}"
OK
AT*TBAND=1,"${BAND4}"
OK
AT*TBAND=1,"${BAND5}"
OK
AT*TBAND=1,"${BAND6}"
OK
AT*TBAND=1,"${BAND7}"
OK
AT*TBAND=1,"${BAND8}"
OK
AT*TBAND=1,"${BAND9}"
OK
AT*TBAND=1,"${BANDA}"
OK
AT*TBAND=1,"${BANDB}"
OK
AT*TBAND=1,"${BANDC}"
OK
AT*TBAND=1,"${BANDD}"
OK
AT*TBAND=1,"${BANDE}"
OK
AT*TBAND=1,"${BANDF}"
OK
AT*TBAND=1,*
ERROR
AT+CMGF?
+CMGF: ${CMGF}\n\nOK
AT+CMGF=?
+CMGF: (0,1)\n\nOK
AT+CMGF=0
OK
AT+CMGF=1
OK
AT+CMGS=*
>
00110003A191F9*
OK\n+CMTI: "ME",1
00510003A191F9*
OK\n+CMTI: "ME",1
00*
+CMGS: 0\n\nOK
AT+CPMS=?
+CPMS: ("SM","ME"),("SM","ME"),("SM")\n\nOK
AT+CPMS="SM","SM","SM"
+CPMS: 0,99,${MSGCOUNT},99,${MSGCOUNT},99\n\nOK
AT+CPMS="ME","ME","SM"
+CPMS: ${MSGCOUNT},99,${MSGCOUNT},99,${MSGCOUNT},99\n\nOK
AT+CGDCONT=?
+CGDCONT: (5-10),("IP"),,,(0-1),(0-1)\n+CGDCONT: (5-10),("IPV6"),,,(0-1),(0-1)\n\nOK
AT+CGDCONT=*
OK
AT+CGACT=*
OK
AT+CGATT=1
OK
AT+CGATT=0
OK
AT+CNMI=?
+CNMI: (0,1,2,3),(0,1),(0,1,2),(0),(0,1)\n\nOK
AT+CNMI=*
OK
AT+CMGL*
AT+CMGD=*
AT+CMGR=*
AT+CSCB=?
+CSCB: (0-1)\n\nOK
AT+CSCB=0,*
OK
AT+CSCB=1,*
OK
AT+CMEE?
+CMEE: ${MEE}\n\nOK
AT+CMEE=?
+CMEE: (0-2)\n\nOK
AT+CMEE=?
OK
AT+CLVL=?
+CLVL: (100-150)\n\nOK
AT+CLVL=*
OK
AT+CLVL?
+CLVL: ${LVL}\n\nOK
AT+CMUT=?
+CMUT: (0,1)\n\nOK
AT+CMUT=*
OK
AT+CMUT?
+CMUT: ${MUT}\n\nOK
AT+CGSMS=?
+CMUT: (0-3)\n\nOK
AT+CGSMS=*
OK
AT+CGSMS?
+CGSMS: ${CGSMS}\n\nOK
AT+FCLASS*
OK
AT+VBT*
ERROR
AT+VCID*
ERROR
AT+VGR*
ERROR
AT+VGT*
ERROR
AT+VGT*
ERROR
AT+VIT*
ERROR
AT+VLS*
ERROR
AT+VRX*
ERROR
AT+VSM*
ERROR
AT+VTS*
OK
AT+VTD*
ERROR
AT+VTX*
ERROR
AT+CPOSR=?
OK
AT+CPOSR=*
OK
AT+CPOSR?
+CPOSR: ${CPOSR}\n\nOK
AT+CPOS=?
OK
AT+CPOS
OK
AT+SIMSTATE?
+SIMSTATE: ${SIMSTATE}\n\nOK
AT+SIMSTATE=?
OK
ATT
OK
ATP
OK
ATA
ERROR
ATH*
OK
ATO*
ERROR
ATS*
OK
ATL*
OK
ATM*
OK
ATI
${ID}\n\nOK
AT+DS*
OK
AT+DR*
OK
AT&C*
OK
AT&D*
OK
AT&F*
OK
AT+GCI
TROLLVILLE\n\nOK
AT+GOI
OK
AT+ICF*
OK
AT+IFC*
OK
AT+ILRR*
OK
AT+IPR*
OK
ATE*
OK
ATQ*
OK
ATV*
OK
ATX*
OK
ATZ*
OK
AT*
AT+GCAP
+CGMI
+CGMM
+CGMR
+CGSN
+CSCS
+WS46
+CSTA
+CHUP
+CBST
+CRLP
+CR
+CEER
+CRC
+CNUM
+CREG
+COPS
+CLCK
+CPWD
+CLIP
+CLIR
+COLP
+CCUG
+CCFC
+CCWA
+CHLD
+CTFR
+CUSD
+CAOC
+CACM
+CAMM
+CPUC
+CCWE
+CSSN
+CPAS
+CFUN
+CPIN
+CBC
+CSQ
+CMEC
+CKPD
+CDIS
+CIND
+CMER
+CCLK
+CALA
+CSIM
+CPBS
+CPBR
+CPBF
+CPBW
+CPOS
+CPOSR
+CMEE
+CMGF
+CMGS
+CUAD
+DR
+DS
+GCAP
+GCI
+GMI
+GMM
+GMR
+GOI
+GSN
+ICF
+IFC
+ILRR
+IPR
+FCLASS
+PTTY
+VBT
+VCID
+VGR
+VGT
+VIP
+VIT
+VLS
+VRX
+VSM
+VTS
+VTD
+VTX
*ECAM
A
D
E
H
I
L
M
O
P
Q
S0
S3
S4
S5
S6
S7
S8
S10
T
V
X
Z
&C
&D
&F
*
OK
AT+PTTY=?
+PTTY: (0-1)\n\nOK
AT+PTTY=*
OK
AT+PTTY?
+PTTY: ${PTTY}\n\nOK
AT+CUAD
+CUAD: "611B4F10A0000000871002FFFFFFFF8905080000FFFFFFFFFFFFFFFFFFFFFFFFFF611F4F0CA000000063504B43532D313550094D49445066696C657351043F007F80"\n\nOK
AT+CUAD=?
OK
98 94 22 02 47 54 21 24 60 F6
08 09 10 10 10 32 54 76 98
01 2E 28 11 4F 01 00 00 00 E8 FF FF FF FF FF FF FF FF FF FF
01 08 08 21 4F 02 00 00 00 1F FF FF FF FF FF FF FF FF FF FF
01 18 10 11 4F 03 00 00 00 32 FF FF FF FF FF FF FF FF FF FF
01 08 08 11 4F 04 00 00 00 0A FF FF FF FF FF FF FF FF FF FF
01 05 05 11 4F 05 00 00 00 08 FF FF FF FF FF FF FF FF FF FF
2E 28 00 00 00 00 00 00 00 01 FF 80 00 00 00 0F
FF 00 00 00 00 77 FE 00 00 00 01 BF F8 00 00 00
06 FF E0 00 00 00 1A 03 80 00 00 00 6B F6 BC 00
00 01 AF D8 38 00 00 06 BF 60 20 00 00 1A FD 80
40 00 00 6B F6 00 80 00 01 A0 1F 02 00 00 06 FF
E4 04 00 00 1B FF 90 10 00 00 6D EE 40 40 00 01
BF F9 01 00 00 6F FF E4 04 00 00 1B FF 90 10 00
00 6F FE 40 40 00 01 BF F9 01 00 00 06 FF E6 04
00 00 1B FF 88 10 00 00 6F FE 20 40 00 01 BF F8
66 00 00 06 FF E0 F0 00 00 1B FF 80 80 00 00 7F
FE 00 00 00 03 00 0C 00 00 00 1F FF F8 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1C 21 08 44 EE 00 48 C4 31 92 20 01 25 11 45 50
80 07 14 45 15 43 80 12 71 1C 4D 08 00 4A 24 89
32 20 01 C8 9E 24 4E E0
08 08 02 03 00 16 AA AA 80 02 85 42 81 42 81 42
81 52 80 02 AA AA FF 00 00 00 FF 00 00 00 FF
18 10 FF FF FF 80 00 01 80 00 01 80 00 01 8F 3C
F1 89 20 81 89 20 81 89 20 F1 89 20 11 89 20 11
89 20 11 8F 3C F1 80 00 01 80 00 01 80 00 01 FF
FF FF
08 08 FF 03 A5 99 99 A5 C3 FF
05 05 FE EB BF FF FF FF
03 6F 46 6F 6E 6F FF FF FF FF FF FF FF FF FF FF FF
4F 57 4E 20 4E 55 4D 42 45 52 FF FF FF FF
07 81 53 58 10 32 54 76 FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF
3C 00 FC 0C 00 00 7F DF 00 31 0F C0
00
03 E7 FF FF FF FF FF FF FF FF FF FF FF FF
10 01 FF FF FF FF FF FF FF FF FF FF FF FF
00 32 00 32 FF FF FF FF FF FF FF FF FF FF FF FF
01 1E FF FF FF FF FF FF FF FF FF FF FF FF FF FF
41 42 43 FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
03 81 21 F3 FF FF FF FF FF FF FF FF FF FF 44 45
46 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF 03 81
89 67 FF FF FF FF FF FF FF FF FF FF
43 42 41 FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
03 81 23 F1 FF FF FF FF FF FF FF FF FF FF
01 02 FF 00
11 F2 FF 00
FD FF FF FF FF FF FF FF FF FF FF FF FF 09
91 11 22 33 44 55 66 77 F8 FF FF FF FF FF
A3 05 80 03 42 F6 18
42 F6 1D 00 00 FF FE 01
43 08 80 D4 3A 1E 34 7C B7 DB 80 04 49 6E 66 6F FF FF FF FF
43 05 84 CC B7 FB 0C 45 06 85 53 F4 5B 4E 07 FF FF FF FF FF
01 01 00 00 00 00
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF 03 81 76 98 FF FF FF FF FF FF FF FF FF FF
01 00 00 00 00
00 FF FF 02
00 01 02 03 04 05
FF FF FF FF FF FF
2E 65 44 65 73 6B FF FF FF FF FF FF FF FF
04 FF 1A 01 FB FF FF FF FF FF FF FF FF FF
31 31 32 FF FF FF FF FF FF FF FF FF FF FF
03 81 11 F2 FF FF FF FF FF FF FF FF FF FF
45 6D 65 72 67 65 6E 63 79 FF FF FF FF FF
03 81 99 F9 FF FF FF FF FF FF FF FF FF FF
50 6F 6C 69 63 65 FF FF FF FF FF FF FF FF
03 81 99 F7 FF FF FF FF FF FF FF FF FF FF
46 69 72 65 6D 65 6E FF FF FF FF FF FF FF
03 81 99 F8 FF FF FF FF FF FF FF FF FF FF
53 65 61 20 65 6D 65 72 67 65 6E 63 79 FF
07 91 84 06 11 00 01 F0 FF FF FF FF FF FF
4D 6F 75 6E 74 61 69 6E 20 65 6D 65 72 2E
07 91 84 06 11 00 03 F0 FF FF FF FF FF FF
2E 48 45 4C 50 20 44 45 53 4B FF FF FF FF
03 81 62 10 FF FF FF FF FF FF FF FF FF FF
2E 52 45 43 48 41 52 47 45 FF FF FF FF FF
03 81 55 55 FF FF FF FF FF FF FF FF FF FF
2E 43 72 65 64 69 74 20 6C 65 66 74 FF FF
04 FF 1A 52 FB FF FF FF FF FF FF FF FF FF
2E 45 6E 67 6C 69 73 68 FF FF FF FF FF FF
05 FF 1A 50 1A B0 FF FF FF FF FF FF FF FF
2E 53 70 61 6E 69 73 68 FF FF FF FF FF FF
05 FF 1A 50 2A B0 FF FF FF FF FF FF FF FF
2E 56 6D 61 69 6C 2E 20 73 74 61 74 75 73
04 FF 1A 22 FB FF FF FF FF FF FF FF FF FF
2E 56 6F 69 63 65 6D 61 69 6C 20 6F 66 66
05 FF 1A 22 0A B0 FF FF FF FF FF FF FF FF
2E 56 6F 69 63 65 6D 61 69 6C 20 6F 6E FF
05 FF 1A 22 1A B1 FF FF FF FF FF FF FF FF
2E 52 6F 61 6D 69 6E 67 20 6F 6E FF FF FF
07 FF 1A 10 1A A1 10 FB FF FF FF FF FF FF
2E 52 6F 61 6D 69 6E 67 20 6F 66 66 FF FF
07 FF 1A 10 0A A0 10 FB FF FF FF FF FF FF
2E 47 50 52 53 2F 4D 4D 53 20 6F 6E FF FF
07 FF 1A 10 1A A1 20 FB FF FF FF FF FF FF
2E 47 50 52 53 2F 4D 4D 53 20 6F 66 66 FF
07 FF 1A 10 0A A0 20 FB FF FF FF FF FF FF
2E 41 63 74 2E 20 73 65 72 76 69 63 65 73
04 FF 1A 10 FB FF FF FF FF FF FF FF FF FF
2E 53 65 6C 65 63 74 20 54 45 41 4D 37 FF
05 FF 1A 74 7A B0 FF FF FF FF FF FF FF FF
2E 53 65 6C 65 63 74 20 45 41 53 59 FF FF
05 FF 1A 74 8A B0 FF FF FF FF FF FF FF FF
2E 56 6F 69 63 65 6D 61 69 6C FF FF FF FF
07 91 84 06 21 22 22 F2 FF FF FF FF FF FF
2E 56 6F 69 63 65 20 61 63 63 65 73 73 FF
07 91 84 06 11 40 44 F4 FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF
02 FF 03 00
55 55
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF 03 81 76 90 FF FF FF FF FF FF FF FF FF FF
5A 55
61 1B 4F 10 A0 00 00 00 87 10 02 FF FF FF FF 89 05 08 00 00 FF FF
FF FF FF FF FF FF FF FF FF FF FF
61 1F 4F 0C A0 00 00 00 63 50 4B 43 53 2D 31 35 50 09 4D 49 44 50
66 69 6C 65 73 51 04 3F 00 7F 80"
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 80
63 70 68 73 11 73 70 6E
63 70 68 73 11 73 70 6E 73 FF
./tests/data/valgrind.suppression 0000644 0000156 0000165 00000002775 12701153654 017311 0 ustar jenkins jenkins {
Ignore pthreads
Memcheck:Leak
...
fun:pthread_create@@*
}
{
Glib memalign
Memcheck:Leak
...
fun:posix_memalign
}
{
Ignore glib mainloop
Memcheck:Leak
...
fun:g_main_context_push_thread_default
}
{
Ignore glib main context
Memcheck:Leak
...
fun:g_main_context_new
}
###############################
# DBus
###############################
{
Memcheck:Param
epoll_ctl(event)
fun:epoll_ctl
obj:/bin/dbus-daemon
...
fun:(below main)
}
###############################
# GObject rules
###############################
{
Memcheck:Leak
...
fun:g_type_register_static
}
{
Memcheck:Leak
...
fun:g_type_register_fundamental
}
{
Memcheck:Leak
...
fun:type_node_fundamental_new_W
}
{
Memcheck:Leak
...
fun:type_data_make_W
}
{
Memcheck:Leak
...
fun:g_type_add_interface_static
}
{
Memcheck:Leak
...
fun:type_iface_vtable_base_init_Wm
}
{
Memcheck:Leak
...
fun:g_dbus_interface_skeleton_class_intern_init
}
{
Memcheck:Leak
...
fun:g_signal_type_cclosure_new
}
{
Memcheck:Leak
fun:calloc
fun:g_malloc0
fun:g_type_class_ref
}
./tests/data/CMakeLists.txt 0000644 0000156 0000165 00000000216 12701153654 015713 0 ustar jenkins jenkins install (
FILES "${CMAKE_CURRENT_SOURCE_DIR}/phonesim/pin-unlock.xml"
DESTINATION "${CMAKE_INSTALL_DATADIR}/indicator-network/phonesim/"
) ./tests/autopilot/ 0000755 0000156 0000165 00000000000 12701153654 014263 5 ustar jenkins jenkins ./tests/autopilot/README 0000644 0000156 0000165 00000000424 12701153654 015143 0 ustar jenkins jenkins
Running from a source tree:
$ export INDICATOR_NETWORK_PHONESIM_DATA=`pwd`/../data/phonesim/
$ autopilot3 run indicator_network
Running tests under unity7:
indicator-network has to be started manually under unity7 before running the tests:
$ initctl start indicator-network
./tests/autopilot/indicator_network/ 0000755 0000156 0000165 00000000000 12701153654 020010 5 ustar jenkins jenkins ./tests/autopilot/indicator_network/__init__.py 0000644 0000156 0000165 00000001420 12701153654 022116 0 ustar jenkins jenkins # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
#
# Unity Indicators Autopilot Test Suite
# Copyright (C) 2014 Canonical
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
./tests/autopilot/indicator_network/tests/ 0000755 0000156 0000165 00000000000 12701153654 021152 5 ustar jenkins jenkins ./tests/autopilot/indicator_network/tests/__init__.py 0000644 0000156 0000165 00000001420 12701153654 023260 0 ustar jenkins jenkins # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
#
# Unity Indicators Autopilot Test Suite
# Copyright (C) 2014 Canonical
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
./tests/autopilot/indicator_network/tests/test_unlock_sim.py 0000644 0000156 0000165 00000012074 12701153654 024732 0 ustar jenkins jenkins # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
#
# Unity Indicators Autopilot Test Suite
# Copyright (C) 2014 Canonical
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import absolute_import
import os
import sysconfig
from testtools.matchers import Equals, NotEquals
from autopilot import input
from autopilot.matchers import Eventually
from pkg_resources import resource_filename
from unity8.process_helpers import unlock_unity
from unity8.shell.tests import UnityTestCase, _get_device_emulation_scenarios
from indicator_network.helpers.phonesim_manager import PhonesimManager
# FIXME:
# This is a workaround for https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1314390 # noqa
# Remove once fixed in upstream and available through repos
from ubuntuuitoolkit import emulators as toolkit_emulators
class QQuickListView(toolkit_emulators.QQuickListView):
def _get_top_container(self):
"""Return the top-most container with a globalRect."""
root = self.get_root_instance()
return root.get_children()[0].get_children()[1]
class UnlockSimTestCase(UnityTestCase):
scenarios = _get_device_emulation_scenarios()
def get_lockscreen(self):
return self.unity_proxy.wait_select_single('Notifications', objectName='notificationList').wait_select_single('Lockscreen')
def get_pinPadButton(self, buttonId):
return self.get_lockscreen().wait_select_single(
"PinPadButton",
objectName="pinPadButton%i" % buttonId
)
def get_pinPadButtonErase(self):
return self.get_lockscreen().wait_select_single(
'PinPadButton',
objectName='pinPadButtonErase'
)
def setUp(self):
super(UnlockSimTestCase, self).setUp()
phonesim_datadir = os.getenv('INDICATOR_NETWORK_PHONESIM_DATA')
if phonesim_datadir == None:
phonesim_datadir = sysconfig.get_config_var('datarootdir') + '/indicator-network/phonesim'
sims = [('sim1',
23456,
phonesim_datadir + '/pin-unlock.xml'),]
self.phonesim_manager = PhonesimManager(sims)
self.phonesim_manager.start_phonesim_processes()
self.phonesim_manager.remove_all_ofono()
self.phonesim_manager.add_ofono('sim1')
self.phonesim_manager.power_on('sim1')
self.unity_proxy = self.launch_unity()
unlock_unity(self.unity_proxy)
self.pointing_device = input.Pointer(device=input.Touch.create())
def tearDown(self):
self.phonesim_manager.shutdown()
super(UnlockSimTestCase, self).tearDown()
def test_unlock_sim(self):
"""Unlock the SIM via the network indicator, entering PIN."""
self.assertThat(
self.phonesim_manager.get_required_pin('sim1'),
Equals('pin')
)
indicator_network_widget = self.main_window._get_indicator_widget(
'indicator-network'
)
self.assertThat(
indicator_network_widget.leftLabel,
Eventually(Equals('SIM Locked'))
)
indicator_page = self.main_window.open_indicator_page(
'indicator-network'
)
list_view = indicator_page.select_single(
'QQuickListView',
objectName='mainMenu'
)
unlock_sim_standard = list_view.wait_select_single(
'Standard',
objectName='indicator.sim.unlock'
)
self.assertTrue(unlock_sim_standard.visible)
list_view.click_element('indicator.sim.unlock')
# get the lockscreen from snap decisions.
pin_lockscreen = self.get_lockscreen()
# FIXME: make helper? Or generalize what's in unity8/shell/tests?
pin_pad_button_1 = self.get_pinPadButton(1)
pin_pad_button_2 = self.get_pinPadButton(2)
pin_pad_button_3 = self.get_pinPadButton(3)
pin_pad_button_4 = self.get_pinPadButton(4)
pin_pad_button_erase = self.get_pinPadButtonErase()
self.pointing_device.click_object(pin_pad_button_1)
self.pointing_device.click_object(pin_pad_button_2)
self.pointing_device.click_object(pin_pad_button_3)
self.pointing_device.click_object(pin_pad_button_4)
self.pointing_device.click_object(pin_pad_button_erase)
self.assertThat(
indicator_network_widget.leftLabel,
Eventually(NotEquals('SIM Locked'))
)
self.assertThat(
self.phonesim_manager.get_required_pin('sim1'),
Equals('none')
)
./tests/autopilot/indicator_network/data/ 0000755 0000156 0000165 00000000000 12701153654 020721 5 ustar jenkins jenkins ./tests/autopilot/indicator_network/data/pin-unlock.xml 0000644 0000156 0000165 00000301416 12701153654 023527 0 ustar jenkins jenkins
AT+CGMI
${GMI}\n\nOK
AT+CGMI=?
OK
AT+GMI
${GMI}\n\nOK
AT+CGMM
${GMM}\n\nOK
AT+GMM
${GMM}\n\nOK
AT+CGMM=?
OK
AT+CGMR
${GMR}\n\nOK
AT+GMR
${GMR}\n\nOK
AT+CGMR=?
OK
AT+CGSN
${GSN}\n\nOK
AT+CGSN=?
OK
AT+GSN
${GSN}\n\nOK
AT+CIMI
${IMSI}\n\nOK
AT+CIMI=?
OK
AT+CSCS?
+CSCS: "${SCS}"\n\nOK
AT+CSCS=?
+CSCS: "GSM","IRA","PCCP437","PCDN","8859-1","HEX","UCS2"\n\nOK
AT+CSCS="*"
OK
AT+WS46?
12\n\nOK
AT+WS46=?
(12)\n\nOK
AT+WS46=12
OK
AT+CSTA?
${STA}\n\nOK
AT+CSTA=?
(129, 145)\n\nOK
AT+CSTA=129
OK
AT+CSTA=145
OK
AT+CBST?
+CBST: 0\n\nOK
AT+CBST=?
+CBST: (0),(0),(0)\n\nOK
AT+CBST=*
OK
AT+CRLP?
+CRLP: 61,61,48,6\n\nOK
AT+CRLP=?
+CRLP: (61),(61),(48),(6)\n\nOK
AT+CRLP=*
OK
AT+CR?
+CR: ${CR}\n\nOK
AT+CR=?
+CR: (0,1)\n\nOK
AT+CR=0
OK
AT+CR=1
OK
AT+CEER
+CEER: ${ERR}\n\nOK
AT+CRC?
+CRC: ${CRC}\n\nOK
AT+CRC=?
+CRC: (0,1)\n\nOK
AT+CRC=0
OK
AT+CRC=1
OK
AT*ECAM?
*ECAM: ${ECAM}\n\nOK
AT*ECAM=?
*ECAM: (0,1)\n\nOK
AT*ECAM=0
OK
AT*ECAM=1
OK
AT+CNUM
+CNUM: ,"+358501234567",145,,4\n\nOK
AT+CNUM=?
OK
AT+CREG?
+CREG: ${REG},1\n\nOK
AT+CREG=?
+CREG: (0,1,2)\n\nOK
AT+CREG=*
OK
AT+CGREG?
+CGREG: ${GREG},1\n\nOK
AT+CGREG=?
+CGREG: (0,1,2)\n\nOK
AT+CGREG=*
OK
AT+COPN
+COPN: ${OP1PLMN},"${OP1}"\n+COPN: ${OP2PLMN},"${OP2}"\n+COPN: ${OP3PLMN},"${OP3}"\n+COPN: ${OP4PLMN},"${OP4}"\n+COPN: ${OP5PLMN},"${OP5}"\n+COPN: ${OP6PLMN},"${OP6}"\n+COPN: ${OP7PLMN},"${OP7}"\n+COPN: ${OP8PLMN},"${OP8}"\n+COPN: ${OP9PLMN},"${OP9}"\n+COPN: ${OP10PLMN},"${OP10}"\n+COPN: ${OP11PLMN},"${OP11}"\n\nOK
AT+COPS?
+COPS: ${OPMODE},${OPFORMAT},${OPDATA}\n\nOK
AT+COPS=3,2;+COPS?;+COPS=3,0;+COPS?
+COPS: 0,2,"${OPPLMN}"\n+COPS: 0,0,"${OP}"\n\nOK
AT+COPS=?
+COPS: (${OP1STATE},"${OP1}","TTAU","${OP1PLMN}",2),(${OP2STATE},"${OP2}","MFN","${OP2PLMN}",0),(${OP2STATE},"${OP2}","MFN","${OP2PLMN}",2),(${OP3STATE},"${OP3}","CNT","${OP3PLMN}"),(${OP4STATE},"${OP4}","BNT","${OP4PLMN}"),(${OP5STATE},"${OP5}","INT","${OP5PLMN}"),(${OP6STATE},"${OP6}","PNT","${OP6PLMN}"),(${OP7STATE},"${OP7}","TNT","${OP7PLMN}"),(${OP8STATE},"${OP8}","MNT","${OP8PLMN}"),(${OP9STATE},"${OP9}","IMSI","${OP9PLMN}"),(${OP10STATE},"${OP10}","NOT","${OP10PLMN}"),(${OP11STATE},"${OP11}","SER","${OP11PLMN}"),(${OP1STATE},"${OP1}","TTAU","${OP1PLMN}",0)\n\nOK
AT+COPS=3,0
OK
AT+COPS=3,2
OK
AT+COPS=0*
OK
AT+COPS=1,0,"${OP1}"
OK
AT+COPS=1,2,"${OP1PLMN}"
OK
AT+COPS=1,0,${OP2}
ERROR
AT+COPS=1,0,${OP3}
ERROR
AT+COPS=1,0,${OP4}
ERROR
AT+COPS=1,2,${OP2PLMN}
ERROR
AT+COPS=1,2,${OP3PLMN}
ERROR
AT+COPS=1,2,${OP4PLMN}
ERROR
AT+COPS=1,0,"${OP6}"
OK
AT+COPS=1,2,"${OP6PLMN}"
OK
AT+COPS=1,0,"${OP7}"
OK
AT+COPS=1,2,"${OP7PLMN}"
OK
AT+COPS=1,0,"${OP8}"
OK
AT+COPS=1,2,"${OP8PLMN}"
OK
AT+COPS=1,0,"${OP9}"
+CMS ERROR: 30
AT+COPS=1,2,${OP9PLMN}
+CMS ERROR: 30
AT+COPS=1,0,"${OP10}"
+CME ERROR: 32
AT+COPS=1,2,${OP10PLMN}
+CME ERROR: 32
AT+COPS=1,0,"${OP11}"
+CME ERROR: 30
AT+COPS=1,2,${OP11PLMN}
+CME ERROR: 30
AT+CPLS?
+CPLS: 0\n\nOK -->
AT+CPOL?
+CPOL: ${PO1}\n+CPOL: ${PO2}\n\nOK
AT+CPOL=1,2,*
OK
AT+CPOL=1
OK
AT+CPOL=2,2,*
OK
AT+CPOL=2
OK
AT+CPOL=3,2,*
OK
AT+CPOL=3
OK
AT+CPOL=4,2,*
OK
AT+CPOL=4
OK
AT+CPOL=5,2,*
OK
AT+CPOL=5
OK
AT+CPOL=6,2,*
OK
AT+CPOL=6
OK
AT+CPOL=7,2,*
OK
AT+CPOL=7
OK
AT+CPOL=8,2,*
OK
AT+CPOL=8
OK
AT+CLCK="AO",1,"${PIN2VALUE}",1
OK
AT+CLCK="AO",2
+CLCK: ${BARVAO},1\n\nOK
AT+CLCK="OI",1,"${PIN2VALUE}",1
OK
AT+CLCK="OI",2
+CLCK: ${BARVOI},1\n\nOK
AT+CLCK="OX",1,"${PIN2VALUE}",1
OK
AT+CLCK="OX",2
+CLCK: ${BARVOX},1\n\nOK
AT+CLCK="AI",1,"${PIN2VALUE}",1
OK
AT+CLCK="AI",2
+CLCK: ${BARVAI},1\n\nOK
AT+CLCK="IR",1,"${PIN2VALUE}",1
OK
AT+CLCK="IR",2
+CLCK: ${BARVIR},1\n\nOK
AT+CLCK="NT",1,"${PIN2VALUE}",1
OK
AT+CLCK="NT",2
+CLCK: ${BARVNT},7\n\nOK
AT+CLCK="NM",1,"${PIN2VALUE}",1
OK
AT+CLCK="NM",2
+CLCK: ${BARVNM},7\n\nOK
AT+CLCK="NS",1,"${PIN2VALUE}",1
OK
AT+CLCK="NS",2
+CLCK: ${BARVNS},7\n\nOK
AT+CLCK="NA",1,"${PIN2VALUE}",1
OK
AT+CLCK="NA",2
+CLCK: ${BARVNA},7\n\nOK
AT+CLCK="AB",0,"${PIN2VALUE}"
OK
AT+CLCK="AG",0,"${PIN2VALUE}",1
OK
AT+CLCK="AC",0,"${PIN2VALUE}",1
OK
AT+CLCK=?
+CLCK: PS(8),SC(8)\n\nOK
AT+CLCK="FD",2
+CLCK: ${FD}\n\nOK
AT+CLCK="FD",0,"${PIN2VALUE}"
OK
AT+CLCK="FD",1,"${PIN2VALUE}"
OK
AT+CLCK="FD",*
ERROR
AT+CLCK="SC",2
+CLCK: ${SC}\n\nOK
AT+CLCK="SC",0,"${PINVALUE}"
OK
AT+CLCK="SC",1,"${PINVALUE}"
OK
AT+CLCK="SC",*
ERROR
AT+CLCK="PS",2
+CLCK: ${PS}\n\nOK
AT+CLCK="PS",0,"${PSPINVALUE}"
OK
AT+CLCK="PS",1,"${PSPINVALUE}"
OK
AT+CLCK="PS",*
ERROR
AT+CPWD="PS","${PSPINVALUE}","*"
OK
AT+CPWD="AB","${PIN2VALUE}","*"
OK
AT+CPWD="AO","${PIN2VALUE}","*"
OK
AT+CPWD="OI","${PIN2VALUE}","*"
OK
AT+CPWD="OX","${PIN2VALUE}","*"
OK
AT+CPWD="AI","${PIN2VALUE}","*"
OK
AT+CPWD="IR","${PIN2VALUE}","*"
OK
AT+CPWD="NT","${PIN2VALUE}","*"
OK
AT+CPWD="NM","${PIN2VALUE}","*"
OK
AT+CPWD="NS","${PIN2VALUE}","*"
OK
AT+CPWD="NA","${PIN2VALUE}","*"
OK
AT+CLIP?
+CLIP: ${LIP},1\n\nOK
AT+CLIP=?
+CLIP: (0,1)\n\nOK
AT+CLIP=*
OK
AT+CDIP?
+CDIP: ${DIP},1\n\nOK
AT+CDIP=?
+CDIP: (0,1)\n\nOK
AT+CDIP=*
OK
AT+CNAP?
+CNAP: ${NAP},1\n\nOK
AT+CNAP=?
+CNAP: (0,1)\n\nOK
AT+CNAP=*
OK
AT+CLIR?
+CLIR: ${LIR},${LIR_STATUS}\n\nOK
AT+CLIR=?
+CLIR: (0,1,2)\n\nOK
AT+CLIR=*
OK
AT+COLP?
+COLP: ${OLP},1\n\nOK
AT+COLP=?
+COLP: (0,1)\n\nOK
AT+COLP=*
OK
AT+COLR
+COLR: 1\n\nOK
AT+COLR=?
OK
AT+CCUG?
+CCUG: 0,0,0\n\nOK
AT+CCUG*
OK
AT+CCFC=?
+CCFC: (0,1,2,3,4,5)\n\nOK
AT+CCFC=2,3,*,145,1,,,20
OK
AT+CCFC=2,3,*,129,1,,,20
OK
AT+CCFC=2,3,*,145,1,,,30
OK
AT+CCFC=2,3,*,129,1,,,30
OK
AT+CCFC=3,3,*,145,1
OK
AT+CCFC=3,3,*,129,1
OK
AT+CCFC=0,3,*,145,1
OK
AT+CCFC=0,3,*,129,1
OK
AT+CCFC=1,3,*,145,1
OK
AT+CCFC=1,3,*,129,1
OK
AT+CCFC=4,4
OK
AT+CCFC=5,4
OK
AT+CCFC=0,4
OK
AT+CCFC=0,4,,,1
OK
AT+CCFC=0,4,,,2
OK
AT+CCFC=0,4,,,4
OK
AT+CCFC=0,4,,,8
OK
AT+CCFC=1,4
OK
AT+CCFC=1,4,,,1
OK
AT+CCFC=1,4,,,2
OK
AT+CCFC=1,4,,,4
OK
AT+CCFC=1,4,,,8
OK
AT+CCFC=2,4
OK
AT+CCFC=2,4,,,1
OK
AT+CCFC=2,4,,,2
OK
AT+CCFC=2,4,,,4
OK
AT+CCFC=2,4,,,8
OK
AT+CCFC=3,4
OK
AT+CCFC=3,4,,,1
OK
AT+CCFC=3,4,,,2
OK
AT+CCFC=3,4,,,4
OK
AT+CCFC=3,4,,,8
OK
AT+CCFC=0,2
+CCFC: ${CF0C1},1,${CF0C1N},${CF0C1T}\n+CCFC: ${CF0C2},2,${CF0C2N}\n+CCFC: ${CF0C4},4,${CF0C4N}\n+CCFC: ${CF0C8},8,${CF0C8N}\n\nOK
AT+CCFC=1,2
+CCFC: ${CF1C1},1,${CF1C1N},${CF1C1T}\n+CCFC: ${CF1C2},2,${CF1C2N}\n+CCFC: ${CF1C4},4,${CF1C4N}\n+CCFC: ${CF1C8},8,${CF1C8N}\n\nOK
AT+CCFC=2,2
+CCFC: ${CF2C1},1,${CF2C1N},${CF2C1T},,,${CF2C1O}\n+CCFC: ${CF2C2},2,${CF2C2N}\n+CCFC: ${CF2C4},4,${CF2C4N}\n+CCFC: ${CF2C8},8,${CF2C8N}\n\nOK
AT+CCFC=3,2
+CCFC: ${CF3C1},1,${CF3C1N},${CF3C1T}\n+CCFC: ${CF3C2},2,${CF3C2N}\n+CCFC: ${CF3C4},4,${CF3C4N}\n+CCFC: ${CF3C8},8,${CF3C8N}\n\nOK
AT+CCWA?
+CCWA: 1\n\nOK
AT+CCWA=1,2
+CCWA: ${CWA_V},1\n+CCWA: ${CWA_D},2\n+CCWA: ${CWA_F},4\n\nOK
AT+CCWA=1,2,7
+CCWA: ${CWA_V},1\n+CCWA: ${CWA_D},2\n+CCWA: ${CWA_F},4\n\nOK
AT+CCWA=1,2,1
+CCWA: ${CWA_V},1\n\nOK
AT+CCWA=1,2,2
+CCWA: ${CWA_D},2\n\nOK
AT+CCWA=1,2,4
+CCWA: ${CWA_F},4\n\nOK
AT+CCWA=1,2,3
+CCWA: ${CWA_V},1\n+CCWA: ${CWA_D},2\n\nOK
AT+CCWA=1,2,5
+CCWA: ${CWA_V},1\n+CCWA: ${CWA_F},4\n\nOK
AT+CCWA=1,2,6
+CCWA: ${CWA_D},2\n+CCWA: ${CWA_F},4\n\nOK
AT+CCWA=?
+CCWA: (0,1)\n\nOK
AT+CCWA=1
OK
AT+CCWA=1,0,1OK
AT+CCWA=1,0,2OK
AT+CCWA=1,0,3OK
AT+CCWA=1,0,4OK
AT+CCWA=1,0,5OK
AT+CCWA=1,0,6OK
AT+CCWA=1,0,7OK
AT+CCWA=1,1,1OK
AT+CCWA=1,1,2OK
AT+CCWA=1,1,3OK
AT+CCWA=1,1,4OK
AT+CCWA=1,1,5OK
AT+CCWA=1,1,6OK
AT+CCWA=1,1,7OK
AT+CUSD?
+CUSD: ${USD}\n\nOK
AT+CUSD=?
+CUSD: (0,1)\n\nOK
AT+CUSD=1,"*225#",15
+CUSD: 0,"Thank you, your request is being processed. A message will be sent to your phone.",15\n\nOK
AT+CUSD=1,"response",15
+CUSD: 0,"Thank you.",15\n\nOK
AT+CUSD=1,"ABCD",240
+CUSD: 0,"USSD string received from SS",240\n\nOK
AT+CUSD=1,"41424344",68
+CUSD: 0,"5553534420737472696E672072656365697665642066726F6D205353",68\n\nOK
AT+CUSD=1,"041704140420041004120421042204120423041904220415",72
+CUSD: 0,"005500530053004400200073007400720069006E0067002000720065006300650069007600650064002000660072006F006D002000530053",72\n\nOK
AT+CUSD=1,"*123#",15
+CUSD: 4\n\nOK
AT+CUSD=1,*
OK
AT+CUSD=2
OK
AT+CUSD=1
OK
AT+CUSD=0
OK
AT+CAOC=0
+CAOC: "${AOC}"\n\nOK
AT+CAOC=*
OK
AT+CAOC?
+CAOC: ${AOCMODE}\n\nOK
AT+CAOC=?
+CAOC: (0-2)\n\nOK
AT+CACM="${SIMPIN2VALUE}"
OK
AT+CACM?
+CACM: "${ACM}"\n\nOK
AT+CACM=?
OK
AT+CAMM="*","${SIMPIN2VALUE}"
OK
AT+CAMM?
+CAMM: "${ACMMAX}"\n\nOK
AT+CAMM=?
OK
AT+CPUC="*","${SIMPIN2VALUE}"
OK
AT+CPUC?
+CPUC: "${PPU}"\n\nOK
AT+CPUC=?
OK
AT+CCWE=*
OK
AT+CCWE?
+CCWE: ${CWEMODE}\n\nOK
AT+CCWE=?
+CCWE: (0,1)\n\nOK
AT+CSSN?
+CSSN: ${SSN}\n\nOK
AT+CSSN=?
+CSSN: (0,1),(0,1)\n\nOK
AT+CSSN=*
OK
AT+CPAS
+CPAS: ${PAS}\n\nOK
AT+CPAS=?
+CPAS: (0-5)\n\nOK
AT+CFUN?
+CFUN: ${FUN}\n\nOK
AT+CFUN=?
+CFUN: (1,4)\n\nOK
AT+CFUN=1
OK
AT+CFUN=4
OK\n\n+CREG: 0\n\n+CGREG: 0
AT+CSMS=?
+CSMS=(0)\n\nOK
AT+CSMS?
+CSMS: 0,1,1,1\n\nOK
AT+CSMS=0
+CSMS: 1,1,1\n\nOK
AT+CSCA=?
OK
AT+CSCA?
+CSCA: "${SCA}",${SCAT}\n\nOK
AT+CSCA="*",145
OK
AT+CSCA="*",129
OK
AT+CPINR=?
OK\n
AT+CPINR
+CPINR: SIM PIN,${PINRETRYCOUNT},3\nOK\n
AT+CPIN?
+CPIN: ${PINNAME}\n\nOK
AT+CPIN="${PINVALUE}"
+CPIN: READY\n\nOK
AT+CPWD="P2","${PIN2VALUE}","*"
OK
AT+CPIN="${PUKVALUE}","*"
+CPIN: READY\n\nOK
AT+CPIN="${PUK2VALUE}","*"
+CPIN: READY\n\nOK
AT+CPIN="*","*"
+CPIN: SIM PUK\n\nERROR
AT+CPIN=*
+CPIN: SIM PIN\n\nERROR
AT+CPIN="${PINVALUE}"
+CPIN: READY\n\nOK
AT+CPIN="${PUKVALUE}","*"
+CPIN: READY\n\nOK
AT+CPIN=*
+CPIN: SIM PIN\n\nERROR
AT+CPIN="${PINVALUE}"
+CPIN: READY\n\nOK
AT+CPIN="${PUKVALUE}","*"
+CPIN: READY\n\nOK
AT+CPIN=*
+CPIN: SIM PUK\n\nERROR
AT+CBC
+CBC: ${BC}\n\nOK
AT+CBC=?
+CBC: (0,1,2,3),(1-100)\n\nOK
AT+CCED=1,8
OK\n+CSQ: ${SQ}
AT+CSQ
+CSQ: ${SQ}\n\nOK
AT+CSQ=?
+CSQ: (0-31,99),(0-7,99)\n\nOK
AT+CMEC?
+CMEC: ${MEC}\n\nOK
AT+CMEC=?
+CMEC: (0-2),(0-2),(0-2)\n\nOK
AT+CMEC=*
OK
AT+CKPD=*
OK
AT+CDIS*
OK
AT+CIND=?
+CIND: ("signal",(0-5)),("service",(0-1))\n\nOK
AT+CMER?
+CMER: ${MER}\n\nOK
AT+CMER=?
+CMER: (0-3),(0-2),(0-2),(0-2),(0-1)\n\nOK
AT+CMER=*
OK
AT+CCLK*
OK
AT+CALA*
OK
AT+CSIM*
ERROR
AT*TBAND?
*TBAND: ${BAND}\n\nOK
AT*TBAND=?
*TBAND: "${BAND0}"\n*TBAND: "${BAND1}"\n*TBAND: "${BAND2}"\n*TBAND: "${BAND3}"\n*TBAND: "${BAND4}"\n*TBAND: "${BAND5}"\n*TBAND: "${BAND6}"\n*TBAND: "${BAND7}"\n*TBAND: "${BAND8}"\n*TBAND: "${BAND9}"\n*TBAND: "${BANDA}"\n*TBAND: "${BANDB}"\n*TBAND: "${BANDC}"\n*TBAND: "${BANDD}"\n*TBAND: "${BANDE}"\n*TBAND: "${BANDF}"\n\nOK
AT*TBAND=0
OK
AT*TBAND=1,""
ERROR
AT*TBAND=1,"${BAND0}"
OK
AT*TBAND=1,"${BAND1}"
OK
AT*TBAND=1,"${BAND2}"
OK
AT*TBAND=1,"${BAND3}"
OK
AT*TBAND=1,"${BAND4}"
OK
AT*TBAND=1,"${BAND5}"
OK
AT*TBAND=1,"${BAND6}"
OK
AT*TBAND=1,"${BAND7}"
OK
AT*TBAND=1,"${BAND8}"
OK
AT*TBAND=1,"${BAND9}"
OK
AT*TBAND=1,"${BANDA}"
OK
AT*TBAND=1,"${BANDB}"
OK
AT*TBAND=1,"${BANDC}"
OK
AT*TBAND=1,"${BANDD}"
OK
AT*TBAND=1,"${BANDE}"
OK
AT*TBAND=1,"${BANDF}"
OK
AT*TBAND=1,*
ERROR
AT+CMGF?
+CMGF: ${CMGF}\n\nOK
AT+CMGF=?
+CMGF: (0,1)\n\nOK
AT+CMGF=0
OK
AT+CMGF=1
OK
AT+CMGS=*
>
00110003A191F9*
OK\n+CMTI: "ME",1
00510003A191F9*
OK\n+CMTI: "ME",1
00*
+CMGS: 0\n\nOK
AT+CPMS=?
+CPMS: ("SM","ME"),("SM","ME"),("SM")\n\nOK
AT+CPMS="SM","SM","SM"
+CPMS: 0,99,${MSGCOUNT},99,${MSGCOUNT},99\n\nOK
AT+CPMS="ME","ME","SM"
+CPMS: ${MSGCOUNT},99,${MSGCOUNT},99,${MSGCOUNT},99\n\nOK
AT+CGDCONT=?
+CGDCONT: (5-10),("IP"),,,(0-1),(0-1)\n+CGDCONT: (5-10),("IPV6"),,,(0-1),(0-1)\n\nOK
AT+CGDCONT=*
OK
AT+CGACT=*
OK
AT+CGATT=1
OK
AT+CGATT=0
OK
AT+CNMI=?
+CNMI: (0,1,2,3),(0,1),(0,1,2),(0),(0,1)\n\nOK
AT+CNMI=*
OK
AT+CMGL*
AT+CMGD=*
AT+CMGR=*
AT+CSCB=?
+CSCB: (0-1)\n\nOK
AT+CSCB=0,*
OK
AT+CSCB=1,*
OK
AT+CMEE?
+CMEE: ${MEE}\n\nOK
AT+CMEE=?
+CMEE: (0-2)\n\nOK
AT+CMEE=?
OK
AT+CLVL=?
+CLVL: (100-150)\n\nOK
AT+CLVL=*
OK
AT+CLVL?
+CLVL: ${LVL}\n\nOK
AT+CMUT=?
+CMUT: (0,1)\n\nOK
AT+CMUT=*
OK
AT+CMUT?
+CMUT: ${MUT}\n\nOK
AT+CGSMS=?
+CMUT: (0-3)\n\nOK
AT+CGSMS=*
OK
AT+CGSMS?
+CGSMS: ${CGSMS}\n\nOK
AT+FCLASS*
OK
AT+VBT*
ERROR
AT+VCID*
ERROR
AT+VGR*
ERROR
AT+VGT*
ERROR
AT+VGT*
ERROR
AT+VIT*
ERROR
AT+VLS*
ERROR
AT+VRX*
ERROR
AT+VSM*
ERROR
AT+VTS*
OK
AT+VTD*
ERROR
AT+VTX*
ERROR
AT+CPOSR=?
OK
AT+CPOSR=*
OK
AT+CPOSR?
+CPOSR: ${CPOSR}\n\nOK
AT+CPOS=?
OK
AT+CPOS
OK
AT+SIMSTATE?
+SIMSTATE: ${SIMSTATE}\n\nOK
AT+SIMSTATE=?
OK
ATT
OK
ATP
OK
ATA
ERROR
ATH*
OK
ATO*
ERROR
ATS*
OK
ATL*
OK
ATM*
OK
ATI
${ID}\n\nOK
AT+DS*
OK
AT+DR*
OK
AT&C*
OK
AT&D*
OK
AT&F*
OK
AT+GCI
TROLLVILLE\n\nOK
AT+GOI
OK
AT+ICF*
OK
AT+IFC*
OK
AT+ILRR*
OK
AT+IPR*
OK
ATE*
OK
ATQ*
OK
ATV*
OK
ATX*
OK
ATZ*
OK
AT*
AT+GCAP
+CGMI
+CGMM
+CGMR
+CGSN
+CSCS
+WS46
+CSTA
+CHUP
+CBST
+CRLP
+CR
+CEER
+CRC
+CNUM
+CREG
+COPS
+CLCK
+CPWD
+CLIP
+CLIR
+COLP
+CCUG
+CCFC
+CCWA
+CHLD
+CTFR
+CUSD
+CAOC
+CACM
+CAMM
+CPUC
+CCWE
+CSSN
+CPAS
+CFUN
+CPIN
+CBC
+CSQ
+CMEC
+CKPD
+CDIS
+CIND
+CMER
+CCLK
+CALA
+CSIM
+CPBS
+CPBR
+CPBF
+CPBW
+CPOS
+CPOSR
+CMEE
+CMGF
+CMGS
+CUAD
+DR
+DS
+GCAP
+GCI
+GMI
+GMM
+GMR
+GOI
+GSN
+ICF
+IFC
+ILRR
+IPR
+FCLASS
+PTTY
+VBT
+VCID
+VGR
+VGT
+VIP
+VIT
+VLS
+VRX
+VSM
+VTS
+VTD
+VTX
*ECAM
A
D
E
H
I
L
M
O
P
Q
S0
S3
S4
S5
S6
S7
S8
S10
T
V
X
Z
&C
&D
&F
*
OK
AT+PTTY=?
+PTTY: (0-1)\n\nOK
AT+PTTY=*
OK
AT+PTTY?
+PTTY: ${PTTY}\n\nOK
AT+CUAD
+CUAD: "611B4F10A0000000871002FFFFFFFF8905080000FFFFFFFFFFFFFFFFFFFFFFFFFF611F4F0CA000000063504B43532D313550094D49445066696C657351043F007F80"\n\nOK
AT+CUAD=?
OK
98 94 22 02 47 54 21 24 60 F6
08 09 10 10 10 32 54 76 98
01 2E 28 11 4F 01 00 00 00 E8 FF FF FF FF FF FF FF FF FF FF
01 08 08 21 4F 02 00 00 00 1F FF FF FF FF FF FF FF FF FF FF
01 18 10 11 4F 03 00 00 00 32 FF FF FF FF FF FF FF FF FF FF
01 08 08 11 4F 04 00 00 00 0A FF FF FF FF FF FF FF FF FF FF
01 05 05 11 4F 05 00 00 00 08 FF FF FF FF FF FF FF FF FF FF
2E 28 00 00 00 00 00 00 00 01 FF 80 00 00 00 0F
FF 00 00 00 00 77 FE 00 00 00 01 BF F8 00 00 00
06 FF E0 00 00 00 1A 03 80 00 00 00 6B F6 BC 00
00 01 AF D8 38 00 00 06 BF 60 20 00 00 1A FD 80
40 00 00 6B F6 00 80 00 01 A0 1F 02 00 00 06 FF
E4 04 00 00 1B FF 90 10 00 00 6D EE 40 40 00 01
BF F9 01 00 00 6F FF E4 04 00 00 1B FF 90 10 00
00 6F FE 40 40 00 01 BF F9 01 00 00 06 FF E6 04
00 00 1B FF 88 10 00 00 6F FE 20 40 00 01 BF F8
66 00 00 06 FF E0 F0 00 00 1B FF 80 80 00 00 7F
FE 00 00 00 03 00 0C 00 00 00 1F FF F8 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1C 21 08 44 EE 00 48 C4 31 92 20 01 25 11 45 50
80 07 14 45 15 43 80 12 71 1C 4D 08 00 4A 24 89
32 20 01 C8 9E 24 4E E0
08 08 02 03 00 16 AA AA 80 02 85 42 81 42 81 42
81 52 80 02 AA AA FF 00 00 00 FF 00 00 00 FF
18 10 FF FF FF 80 00 01 80 00 01 80 00 01 8F 3C
F1 89 20 81 89 20 81 89 20 F1 89 20 11 89 20 11
89 20 11 8F 3C F1 80 00 01 80 00 01 80 00 01 FF
FF FF
08 08 FF 03 A5 99 99 A5 C3 FF
05 05 FE EB BF FF FF FF
03 6F 46 6F 6E 6F FF FF FF FF FF FF FF FF FF FF FF
4F 57 4E 20 4E 55 4D 42 45 52 FF FF FF FF
07 81 53 58 10 32 54 76 FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF
3C 00 FC 0C 00 00 7F DF 00 31 0F C0
00
03 E7 FF FF FF FF FF FF FF FF FF FF FF FF
10 01 FF FF FF FF FF FF FF FF FF FF FF FF
00 32 00 32 FF FF FF FF FF FF FF FF FF FF FF FF
01 1E FF FF FF FF FF FF FF FF FF FF FF FF FF FF
41 42 43 FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
03 81 21 F3 FF FF FF FF FF FF FF FF FF FF 44 45
46 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF 03 81
89 67 FF FF FF FF FF FF FF FF FF FF
43 42 41 FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
03 81 23 F1 FF FF FF FF FF FF FF FF FF FF
01 02 FF 00
11 F2 FF 00
FD FF FF FF FF FF FF FF FF FF FF FF FF 09
91 11 22 33 44 55 66 77 F8 FF FF FF FF FF
A3 05 80 03 42 F6 18
42 F6 1D 00 00 FF FE 01
43 08 80 D4 3A 1E 34 7C B7 DB 80 04 49 6E 66 6F FF FF FF FF
43 05 84 CC B7 FB 0C 45 06 85 53 F4 5B 4E 07 FF FF FF FF FF
01 01 00 00 00 00
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF 03 81 76 98 FF FF FF FF FF FF FF FF FF FF
01 00 00 00 00
00 FF FF 02
00 01 02 03 04 05
FF FF FF FF FF FF
2E 65 44 65 73 6B FF FF FF FF FF FF FF FF
04 FF 1A 01 FB FF FF FF FF FF FF FF FF FF
31 31 32 FF FF FF FF FF FF FF FF FF FF FF
03 81 11 F2 FF FF FF FF FF FF FF FF FF FF
45 6D 65 72 67 65 6E 63 79 FF FF FF FF FF
03 81 99 F9 FF FF FF FF FF FF FF FF FF FF
50 6F 6C 69 63 65 FF FF FF FF FF FF FF FF
03 81 99 F7 FF FF FF FF FF FF FF FF FF FF
46 69 72 65 6D 65 6E FF FF FF FF FF FF FF
03 81 99 F8 FF FF FF FF FF FF FF FF FF FF
53 65 61 20 65 6D 65 72 67 65 6E 63 79 FF
07 91 84 06 11 00 01 F0 FF FF FF FF FF FF
4D 6F 75 6E 74 61 69 6E 20 65 6D 65 72 2E
07 91 84 06 11 00 03 F0 FF FF FF FF FF FF
2E 48 45 4C 50 20 44 45 53 4B FF FF FF FF
03 81 62 10 FF FF FF FF FF FF FF FF FF FF
2E 52 45 43 48 41 52 47 45 FF FF FF FF FF
03 81 55 55 FF FF FF FF FF FF FF FF FF FF
2E 43 72 65 64 69 74 20 6C 65 66 74 FF FF
04 FF 1A 52 FB FF FF FF FF FF FF FF FF FF
2E 45 6E 67 6C 69 73 68 FF FF FF FF FF FF
05 FF 1A 50 1A B0 FF FF FF FF FF FF FF FF
2E 53 70 61 6E 69 73 68 FF FF FF FF FF FF
05 FF 1A 50 2A B0 FF FF FF FF FF FF FF FF
2E 56 6D 61 69 6C 2E 20 73 74 61 74 75 73
04 FF 1A 22 FB FF FF FF FF FF FF FF FF FF
2E 56 6F 69 63 65 6D 61 69 6C 20 6F 66 66
05 FF 1A 22 0A B0 FF FF FF FF FF FF FF FF
2E 56 6F 69 63 65 6D 61 69 6C 20 6F 6E FF
05 FF 1A 22 1A B1 FF FF FF FF FF FF FF FF
2E 52 6F 61 6D 69 6E 67 20 6F 6E FF FF FF
07 FF 1A 10 1A A1 10 FB FF FF FF FF FF FF
2E 52 6F 61 6D 69 6E 67 20 6F 66 66 FF FF
07 FF 1A 10 0A A0 10 FB FF FF FF FF FF FF
2E 47 50 52 53 2F 4D 4D 53 20 6F 6E FF FF
07 FF 1A 10 1A A1 20 FB FF FF FF FF FF FF
2E 47 50 52 53 2F 4D 4D 53 20 6F 66 66 FF
07 FF 1A 10 0A A0 20 FB FF FF FF FF FF FF
2E 41 63 74 2E 20 73 65 72 76 69 63 65 73
04 FF 1A 10 FB FF FF FF FF FF FF FF FF FF
2E 53 65 6C 65 63 74 20 54 45 41 4D 37 FF
05 FF 1A 74 7A B0 FF FF FF FF FF FF FF FF
2E 53 65 6C 65 63 74 20 45 41 53 59 FF FF
05 FF 1A 74 8A B0 FF FF FF FF FF FF FF FF
2E 56 6F 69 63 65 6D 61 69 6C FF FF FF FF
07 91 84 06 21 22 22 F2 FF FF FF FF FF FF
2E 56 6F 69 63 65 20 61 63 63 65 73 73 FF
07 91 84 06 11 40 44 F4 FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF
02 FF 03 00
55 55
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF 03 81 76 90 FF FF FF FF FF FF FF FF FF FF
5A 55
61 1B 4F 10 A0 00 00 00 87 10 02 FF FF FF FF 89 05 08 00 00 FF FF
FF FF FF FF FF FF FF FF FF FF FF
61 1F 4F 0C A0 00 00 00 63 50 4B 43 53 2D 31 35 50 09 4D 49 44 50
66 69 6C 65 73 51 04 3F 00 7F 80"
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 80
63 70 68 73 11 73 70 6E
63 70 68 73 11 73 70 6E 73 FF
./tests/autopilot/indicator_network/helpers/ 0000755 0000156 0000165 00000000000 12701153654 021452 5 ustar jenkins jenkins ./tests/autopilot/indicator_network/helpers/__init__.py 0000644 0000156 0000165 00000000000 12701153654 023551 0 ustar jenkins jenkins ./tests/autopilot/indicator_network/helpers/phonesim_manager.py 0000755 0000156 0000165 00000006241 12701153654 025346 0 ustar jenkins jenkins #!/usr/bin/python -tt
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
#
# Unity Indicators Autopilot Test Suite
# Copyright (C) 2014 Canonical
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
from __future__ import absolute_import
import dbus
import subprocess
from time import sleep
class PhonesimManager(object):
def __init__(self, sims, exe=None):
if exe is None:
self.phonesim_exe = '/usr/bin/ofono-phonesim'
else:
self.phonesim_exe = exe
self.sims = sims
self.sim_processes = {}
self.system_bus = dbus.SystemBus()
self.ofono = self.system_bus.get_object('org.ofono', '/')
self.phonesim_manager = dbus.Interface(
self.ofono,
'org.ofono.phonesim.Manager'
)
def start_phonesim_processes(self):
for simname, simport, conffile in self.sims:
cmd = ['/usr/bin/xvfb-run', '-a', self.phonesim_exe, '-p', str(simport), conffile]
p = subprocess.Popen(cmd)
self.sim_processes[simname] = p
# give the processes some time to start
sleep(1)
def shutdown(self):
for p in self.sim_processes.values():
p.kill()
self.sim_processes = {}
def reset_ofono(self):
self.phonesim_manager.Reset()
def remove_all_ofono(self):
self.phonesim_manager.RemoveAll()
def add_ofono(self, name):
for simname, simport, _ in self.sims:
if name == simname:
self.phonesim_manager.Add(simname, '127.0.0.1', str(simport))
return
raise RuntimeError('Tried to add unknown modem %s.' % name)
def power_on(self, sim_name):
sim = self.system_bus.get_object('org.ofono', '/'+sim_name)
modem = dbus.Interface(sim, dbus_interface='org.ofono.Modem')
modem.SetProperty('Powered', True)
sleep(1)
def power_off(self, sim_name):
sim = self.system_bus.get_object('org.ofono', '/'+sim_name)
modem = dbus.Interface(sim, dbus_interface='org.ofono.Modem')
modem.SetProperty('Powered', False)
sleep(1)
def get_required_pin(self, sim_name):
sim = self.system_bus.get_object('org.ofono', '/'+sim_name)
interface = dbus.Interface(sim, dbus_interface='org.ofono.SimManager')
return str(interface.GetProperties()['PinRequired'])
if __name__ == '__main__':
sims = [('sim1', 12345, '/usr/share/phonesim/default.xml'),
('sim2', 12346, '/usr/share/phonesim/default.xml')]
m = PhonesimManager(sims)
m.start_phonesim_processes()
m.shutdown()
./tests/autopilot/setup.py 0000644 0000156 0000165 00000002104 12701153654 015772 0 ustar jenkins jenkins #!/usr/bin/python
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
#
# indicator-network Autopilot Test Suite
# Copyright (C) 2014 Canonical
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
from distutils.core import setup
from setuptools import find_packages
setup(
name='indicator-network',
version='0.1',
description='indicator-network autopilot tests.',
url='https://launchpad.net/indicator-network',
license='GPLv3',
packages=find_packages(),
)
./tests/autopilot/CMakeLists.txt 0000644 0000156 0000165 00000000432 12701153654 017022 0 ustar jenkins jenkins
# list these here to have them visible in Qt Creator
set(AUTOPILOT_FILES
indicator_network/tests/__init__.py
indicator_network/tests/test_unlock_sim.py
indicator_network/helpers/phonesim_manager.py
)
add_custom_target(QtCreatorAutopilotHack SOURCES ${AUTOPILOT_FILES})
./tests/unit/ 0000755 0000156 0000165 00000000000 12701153654 013222 5 ustar jenkins jenkins ./tests/unit/indicator/ 0000755 0000156 0000165 00000000000 12701153654 015176 5 ustar jenkins jenkins ./tests/unit/indicator/menuitems/ 0000755 0000156 0000165 00000000000 12701153654 017204 5 ustar jenkins jenkins ./tests/unit/indicator/menuitems/test-access-point-item.cpp 0000644 0000156 0000165 00000005414 12701153654 024215 0 ustar jenkins jenkins /*
* Copyright (C) 2013 Canonical, Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
* Author: Pete Woods
*/
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace testing;
using namespace QtDBusTest;
using namespace testutils;
using namespace nmofono;
namespace
{
class MockAccessPoint : public wifi::AccessPoint
{
public:
MOCK_CONST_METHOD0(ssid, QString());
MOCK_CONST_METHOD0(bssid, QString());
MOCK_CONST_METHOD0(raw_ssid, QByteArray());
MOCK_CONST_METHOD0(object_path, QDBusObjectPath());
MOCK_CONST_METHOD0(secured, bool());
MOCK_CONST_METHOD0(enterprise, bool());
MOCK_CONST_METHOD0(adhoc, bool());
MOCK_CONST_METHOD0(strength, double());
};
class TestAccessPointItem : public Test
{
protected:
DBusTestRunner dbus;
};
TEST_F(TestAccessPointItem, ExportBasicActionsAndMenu)
{
shared_ptr accessPoint = make_shared<
NiceMock>();
ON_CALL(*accessPoint, ssid()).WillByDefault(Return(QString("the ssid")));
ON_CALL(*accessPoint, secured()).WillByDefault(Return(true));
ON_CALL(*accessPoint, adhoc()).WillByDefault(Return(false));
ON_CALL(*accessPoint, strength()).WillByDefault(Return(70.0));
auto accessPointItem = make_shared(accessPoint);
auto menuItem = accessPointItem->menuItem();
EXPECT_EQ("the ssid", menuItem->label());
EXPECT_FALSE(bool_value(menuItem, "x-canonical-wifi-ap-is-adhoc"));
EXPECT_TRUE(bool_value(menuItem, "x-canonical-wifi-ap-is-secure"));
QString strengthActionName = string_value(
menuItem, "x-canonical-wifi-ap-strength-action");
auto strengthAction = findAction(accessPointItem->actionGroup(),
strengthActionName);
ASSERT_FALSE(strengthAction.get() == nullptr);
EXPECT_EQ(70, strengthAction->state().as());
ON_CALL(*accessPoint, strength()).WillByDefault(Return(20.0));
Q_EMIT accessPoint->strengthUpdated(20.0);
EXPECT_EQ(20, strengthAction->state().as());
}
} // namespace
./tests/unit/indicator/menuitems/test-switch-item.cpp 0000644 0000156 0000165 00000003336 12701153654 023127 0 ustar jenkins jenkins /*
* Copyright (C) 2013 Canonical, Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
* Author: Pete Woods
*/
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace testing;
using namespace QtDBusTest;
using namespace testutils;
namespace
{
class TestSwitchItem : public Test
{
protected:
DBusTestRunner dbus;
};
TEST_F(TestSwitchItem, ExportBasicActionsAndMenu)
{
auto switchItem = make_shared("label", "prefix", "name");
EXPECT_FALSE(switchItem->state());
auto menuItem = switchItem->menuItem();
EXPECT_EQ("label", menuItem->label());
QString name = menuItem->action();
EXPECT_EQ("indicator.prefix.name", name);
auto actionGroup = switchItem->actionGroup();
auto action = findAction(actionGroup, name);
ASSERT_FALSE(action == nullptr);
EXPECT_FALSE(action->state().as());
action->setState(TypedVariant(true));
// FIXME Why can't we make this assertion
// EXPECT_TRUE(switchItem->state());
}
} // namespace
./tests/unit/secret-agent/ 0000755 0000156 0000165 00000000000 12701153654 015603 5 ustar jenkins jenkins ./tests/unit/secret-agent/test-secret-agent.cpp 0000644 0000156 0000165 00000024450 12701153654 021652 0 ustar jenkins jenkins /*
* Copyright (C) 2013 Canonical, Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
* Author: Pete Woods
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace testing;
using namespace QtDBusTest;
using namespace QtDBusMock;
using namespace agent;
namespace mh = unity::gmenuharness;
namespace {
class TestSecretAgentCommon {
protected:
TestSecretAgentCommon() :
dbusMock(dbusTestRunner) {
DBusTypes::registerMetaTypes();
dbusMock.registerNotificationDaemon();
dbusMock.registerNetworkManager();
dbusTestRunner.startServices();
QProcessEnvironment env(QProcessEnvironment::systemEnvironment());
env.insert("SECRET_AGENT_DEBUG_PASSWORD", "1");
secretAgent.setProcessEnvironment(env);
secretAgent.setReadChannel(QProcess::StandardOutput);
secretAgent.setProcessChannelMode(QProcess::ForwardedErrorChannel);
secretAgent.start(SECRET_AGENT_BIN, QStringList() << "--print-address");
secretAgent.waitForStarted();
secretAgent.waitForReadyRead();
agentBus = secretAgent.readAll().trimmed();
agentInterface.reset(
new OrgFreedesktopNetworkManagerSecretAgentInterface(agentBus,
NM_DBUS_PATH_SECRET_AGENT, dbusTestRunner.systemConnection()));
notificationsInterface.reset(
new OrgFreedesktopDBusMockInterface(
"org.freedesktop.Notifications",
"/org/freedesktop/Notifications",
dbusTestRunner.sessionConnection()));
}
virtual ~TestSecretAgentCommon() {
secretAgent.terminate();
secretAgent.waitForFinished();
}
QVariantDictMap connection(const QString &keyManagement) {
QVariantMap wirelessSecurity;
wirelessSecurity[SecretAgent::NM_WIRELESS_SECURITY_KEY_MGMT] =
keyManagement;
QVariantMap conn;
conn[SecretAgent::NM_CONNECTION_ID] = "the ssid";
QVariantDictMap connection;
connection[SecretAgent::NM_WIRELESS_SECURITY_SETTING_NAME] =
wirelessSecurity;
connection[SecretAgent::NM_CONNECTION_SETTING_NAME] = conn;
return connection;
}
QVariantDictMap expected(const QString &keyManagement,
const QString &keyName, const QString &password) {
QVariantMap wirelessSecurity;
wirelessSecurity[SecretAgent::NM_WIRELESS_SECURITY_KEY_MGMT] =
keyManagement;
wirelessSecurity[keyName] = password;
QVariantMap conn;
conn[SecretAgent::NM_CONNECTION_ID] = "the ssid";
QVariantDictMap connection;
connection[SecretAgent::NM_WIRELESS_SECURITY_SETTING_NAME] =
wirelessSecurity;
connection[SecretAgent::NM_CONNECTION_SETTING_NAME] = conn;
return connection;
}
DBusTestRunner dbusTestRunner;
DBusMock dbusMock;
QProcess secretAgent;
QString agentBus;
QScopedPointer agentInterface;
QScopedPointer notificationsInterface;
};
struct TestSecretAgentParams {
QString keyManagement;
QString passwordKey;
QString password;
};
class TestSecretAgentGetSecrets: public TestSecretAgentCommon,
public TestWithParam {
};
static void transform(QVariantMap &map);
static void transform(QVariant &variant) {
if (variant.canConvert()) {
QDBusArgument value(variant.value());
if (value.currentType() == QDBusArgument::MapType) {
QVariantMap map;
value >> map;
transform(map);
variant = map;
}
}
}
static void transform(QVariantMap &map) {
for (auto it(map.begin()); it != map.end(); ++it) {
transform(*it);
}
}
static void transform(QVariantList &list) {
for (auto it(list.begin()); it != list.end(); ++it) {
transform(*it);
}
}
TEST_P(TestSecretAgentGetSecrets, ProvidesPasswordForWpaPsk) {
QDBusPendingReply reply(
agentInterface->GetSecrets(connection(GetParam().keyManagement),
QDBusObjectPath("/connection/foo"),
SecretAgent::NM_WIRELESS_SECURITY_SETTING_NAME, QStringList(),
5));
QSignalSpy notificationSpy(notificationsInterface.data(),
SIGNAL(MethodCalled(const QString &, const QVariantList &)));
notificationSpy.wait();
ASSERT_EQ(1, notificationSpy.size());
const QVariantList &call(notificationSpy.at(0));
ASSERT_EQ("Notify", call.at(0));
QVariantList args(call.at(1).toList());
transform(args);
ASSERT_EQ(8, args.size());
EXPECT_EQ("indicator-network", args.at(0));
EXPECT_EQ("Connect to “the ssid”", args.at(3).toString().toStdString());
QVariantMap hints(args.at(6).toMap());
QVariantMap menuInfo(hints["x-canonical-private-menu-model"].toMap());
QString busName(menuInfo["busName"].toString());
QString menuPath(menuInfo["menuPath"].toString());
QVariantMap actions(menuInfo["actions"].toMap());
vector> stdActions;
QMapIterator it(actions);
while (it.hasNext())
{
it.next();
stdActions.emplace_back(make_pair(it.key().toStdString(), it.value().toString().toStdString()));
}
{
EXPECT_MATCHRESULT(mh::MenuMatcher(mh::MenuMatcher::Parameters(
busName.toStdString(),
stdActions,
menuPath.toStdString()))
.item(mh::MenuItemMatcher()
.label("")
.action("notifications.password")
.set_action_state(shared_ptr(g_variant_new_string(GetParam().password.toUtf8().constData()), &g_variant_unref))
).match());
// The gaction needs an IDLE or it doesn't emit the state change
// So we spin the mainloop with some junk here
shared_ptr o(g_simple_action_new("a", NULL), &mh::g_object_deleter);
mh::waitForCore(G_OBJECT(o.get()), "activate", 100);
ASSERT_EQ("Password received", secretAgent.readAll().trimmed());
}
notificationsInterface->EmitSignal(
OrgFreedesktopNotificationsInterface::staticInterfaceName(),
"ActionInvoked", "us", QVariantList() << 1 << "connect_id");
QVariantDictMap result(reply);
EXPECT_EQ(
expected(GetParam().keyManagement, GetParam().passwordKey,
GetParam().password), result);
}
INSTANTIATE_TEST_CASE_P(WpaPsk, TestSecretAgentGetSecrets,
Values(TestSecretAgentParams( { SecretAgent::NM_KEY_MGMT_WPA_PSK,
SecretAgent::NM_WIRELESS_SECURITY_PSK, "hard-coded-password" })));
INSTANTIATE_TEST_CASE_P(WpaPskLongPassword, TestSecretAgentGetSecrets,
Values(TestSecretAgentParams( { SecretAgent::NM_KEY_MGMT_WPA_PSK,
SecretAgent::NM_WIRELESS_SECURITY_PSK, "123456789012345678901234567890123456789012345678901234" })));
INSTANTIATE_TEST_CASE_P(WpaNone, TestSecretAgentGetSecrets,
Values(TestSecretAgentParams( { SecretAgent::NM_KEY_MGMT_WPA_NONE,
SecretAgent::NM_WIRELESS_SECURITY_PSK, "hard-coded-password" })));
INSTANTIATE_TEST_CASE_P(None, TestSecretAgentGetSecrets,
Values(
TestSecretAgentParams( { SecretAgent::NM_KEY_MGMT_NONE,
SecretAgent::NM_WIRELESS_SECURITY_WEP_KEY0,
"hard-coded-password" })));
class TestSecretAgent: public TestSecretAgentCommon, public Test {
};
TEST_F(TestSecretAgent, GetSecretsWithNone) {
QDBusPendingReply reply(
agentInterface->GetSecrets(
connection(SecretAgent::NM_KEY_MGMT_WPA_PSK),
QDBusObjectPath("/connection/foo"),
SecretAgent::NM_WIRELESS_SECURITY_SETTING_NAME, QStringList(),
0));
reply.waitForFinished();
ASSERT_TRUE(reply.isError());
EXPECT_EQ(QDBusError::InternalError, reply.error().type());
EXPECT_EQ("No password found for this connection.",
reply.error().message());
}
/* Tests that if we request secrets and then cancel the request
that we close the notification */
TEST_F(TestSecretAgent, CancelGetSecrets) {
QSignalSpy notificationSpy(notificationsInterface.data(), SIGNAL(MethodCalled(const QString &, const QVariantList &)));
agentInterface->GetSecrets(
connection(SecretAgent::NM_KEY_MGMT_WPA_PSK),
QDBusObjectPath("/connection/foo"),
SecretAgent::NM_WIRELESS_SECURITY_SETTING_NAME, QStringList(),
5);
notificationSpy.wait();
ASSERT_EQ(1, notificationSpy.size());
const QVariantList &call(notificationSpy.at(0));
ASSERT_EQ("Notify", call.at(0));
notificationSpy.clear();
agentInterface->CancelGetSecrets(QDBusObjectPath("/connection/foo"),
SecretAgent::NM_WIRELESS_SECURITY_SETTING_NAME);
notificationSpy.wait();
ASSERT_EQ(1, notificationSpy.size());
const QVariantList &closecall(notificationSpy.at(0));
ASSERT_EQ("CloseNotification", closecall.at(0));
}
/* Ensures that if we request secrets twice we close the notification
for the first request */
TEST_F(TestSecretAgent, MultiSecrets) {
QSignalSpy notificationSpy(notificationsInterface.data(), SIGNAL(MethodCalled(const QString &, const QVariantList &)));
agentInterface->GetSecrets(
connection(SecretAgent::NM_KEY_MGMT_WPA_PSK),
QDBusObjectPath("/connection/foo"),
SecretAgent::NM_WIRELESS_SECURITY_SETTING_NAME, QStringList(),
5);
notificationSpy.wait();
ASSERT_EQ(1, notificationSpy.size());
const QVariantList &call(notificationSpy.at(0));
ASSERT_EQ("Notify", call.at(0));
notificationSpy.clear();
agentInterface->GetSecrets(
connection(SecretAgent::NM_KEY_MGMT_WPA_PSK),
QDBusObjectPath("/connection/foo2"),
SecretAgent::NM_WIRELESS_SECURITY_SETTING_NAME, QStringList(),
5);
notificationSpy.wait();
notificationSpy.wait();
ASSERT_EQ(2, notificationSpy.size());
const QVariantList &closecall(notificationSpy.at(1));
ASSERT_EQ("CloseNotification", closecall.at(0));
const QVariantList &newnotify(notificationSpy.at(0));
ASSERT_EQ("Notify", newnotify.at(0));
}
TEST_F(TestSecretAgent, SaveSecrets) {
agentInterface->SaveSecrets(QVariantDictMap(),
QDBusObjectPath("/connection/foo")).waitForFinished();
}
TEST_F(TestSecretAgent, DeleteSecrets) {
agentInterface->DeleteSecrets(QVariantDictMap(),
QDBusObjectPath("/connection/foo")).waitForFinished();
}
} // namespace
./tests/unit/secret-agent/secret-agent-main.cpp 0000644 0000156 0000165 00000003574 12701153654 021623 0 ustar jenkins jenkins /*
* Copyright (C) 2015 Canonical, Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
* Author: Pete Woods
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main(int argc, char *argv[]) {
QCoreApplication application(argc, argv);
DBusTypes::registerMetaTypes();
Variant::registerMetaTypes();
setlocale(LC_ALL, "");
bindtextdomain(GETTEXT_PACKAGE, LOCALE_DIR);
textdomain(GETTEXT_PACKAGE);
util::UnixSignalHandler handler([]
{
QCoreApplication::exit(0);
});
handler.setupUnixSignalHandlers();
auto secretAgent = make_unique(
make_shared(GETTEXT_PACKAGE),
make_shared(),
QDBusConnection::systemBus(), QDBusConnection::sessionBus());
if (argc == 2 && QString("--print-address") == argv[1]) {
cout << QDBusConnection::systemBus().baseService().toStdString()
<< endl;
}
return application.exec();
}
./tests/unit/menumodel-cpp/ 0000755 0000156 0000165 00000000000 12701153654 015767 5 ustar jenkins jenkins ./tests/unit/menumodel-cpp/test-menu-exporter.cpp 0000644 0000156 0000165 00000011614 12701153654 022265 0 ustar jenkins jenkins /*
* Copyright © 2014 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
* Authors:
* Antti Kaijanmäki
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace testing;
using namespace QtDBusTest;
namespace mh = unity::gmenuharness;
namespace
{
class TestMenuExporter : public Test
{
protected:
void
SetUp () override
{
Variant::registerMetaTypes();
sessionBus = make_shared();
g_dbus_connection_set_exit_on_close(sessionBus->bus().get(), FALSE);
actionGroup = make_shared();
menu = make_shared