mtp

Merge lp:~cyphermox/mtp/images into lp:mtp

Proposed by Mathieu Trudel-Lapierre
Status: Merged
Approved by: Ricardo Salveti
Approved revision: 24
Merged at revision: 24
Proposed branch: lp:~cyphermox/mtp/images
Merge into: lp:mtp
Diff against target: 1573 lines (+1152/-95)
20 files modified
.bzr-builddeb/default.conf (+2/-0)
CMakeLists.txt (+8/-1)
debian/changelog (+2/-2)
debian/control (+10/-5)
debian/mtp-server.conf (+18/-0)
debian/mtp-server.install (+2/-1)
debian/mtp-server.mtp-server-bootup.upstart (+27/-0)
debian/rules (+5/-7)
server/CMakeLists.txt (+6/-1)
server/UbuntuMtpDatabase.h (+189/-66)
server/server.cpp (+32/-12)
src/MtpUtils.cpp (+1/-0)
tests/CMakeLists.txt (+91/-0)
tests/MockMtpDatabase.h (+358/-0)
tests/TestMtpDebug.cpp (+49/-0)
tests/TestMtpPacket.cpp (+50/-0)
tests/TestMtpProperty.cpp (+95/-0)
tests/TestMtpServer.cpp (+72/-0)
tests/TestMtpStorage.cpp (+87/-0)
tests/TestMtpUtils.cpp (+48/-0)
To merge this branch: bzr merge lp:~cyphermox/mtp/images
Reviewer Review Type Date Requested Status
Ricardo Salveti (community) Approve
Review via email: mp+184868@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Ricardo Salveti (rsalveti) wrote :

105 + timeout=10
106 + # loop 10 times and then exit, if the property service
107 + # isnt up after 80 sec # it is likely not starting at all
108 + while [ ! -e /dev/socket/property_service ]; do
109 + sleep 8
110 + if [ "$timeout" -le 0 ]; then
111 + stop
112 + exit 0
113 + fi
114 + timeout=$(($timeout - 1))
115 + done
116 +
117 + if [ -x /usr/bin/setprop ]; then
118 + /usr/bin/setprop sys.usb.config mtp,adb
119 + fi

You don't need to go over the timeout logic if setprop is not available.

121 + start mtp-server

Why do we need to manually start the mtp-server if the other upstart job is already watching for android_usb-device-changed udev events?

337 + readFiles("/home/phablet");

How hard would it be to not make it hardcoded to phablet? Guess the server would be per user anyway, right?

Rest looks fine, need testing.

review: Needs Information
Revision history for this message
Ricardo Salveti (rsalveti) wrote :

40 -mtp (0.0.1-1) raring; urgency=low
41 -
42 - * Initial release
43 -
44 - -- Thomas Voß <email address hidden> Mon, 10 June 2013 11:43:05 +0200
45 +mtp (0.0.4-0ubuntu1) UNRELEASED; urgency=low

Coming from 0.0.1 to 0.0.4, would probably be better to use 0.1 instead as you're replacing the changelog anyway.

Revision history for this message
Mathieu Trudel-Lapierre (cyphermox) wrote :

> You don't need to go over the timeout logic if setprop is not available.

Well, the timeout is more important, since this could possibly start before the android settings service is available to do something with the request. Should I jsut remove the check for the existence of setprop?

lp:~cyphermox/mtp/images updated
19. By Mathieu Trudel-Lapierre

Un-hardcode paths and user info.

20. By Mathieu Trudel-Lapierre

Fix saving files to the root MTP directory.

21. By Mathieu Trudel-Lapierre

Only check for property service if setprop is executable at all

22. By Mathieu Trudel-Lapierre

Fix changelog for archive release

23. By Mathieu Trudel-Lapierre

Add libboost-test-dev as a Build-Depends.

Revision history for this message
Ricardo Salveti (rsalveti) wrote :

747 +++ tests/MockMtpDatabase.h 2013-09-11 16:07:04 +0000

Mind adding copyright in this file?

review: Needs Fixing
lp:~cyphermox/mtp/images updated
24. By Mathieu Trudel-Lapierre

Fix changelog license for the files we added that are not from the Android library.

Revision history for this message
Ricardo Salveti (rsalveti) wrote :

Looks good, thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory '.bzr-builddeb'
=== added file '.bzr-builddeb/default.conf'
--- .bzr-builddeb/default.conf 1970-01-01 00:00:00 +0000
+++ .bzr-builddeb/default.conf 2013-09-11 16:32:38 +0000
@@ -0,0 +1,2 @@
1[BUILDDEB]
2split = True
03
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2013-06-13 10:22:21 +0000
+++ CMakeLists.txt 2013-09-11 16:32:38 +0000
@@ -10,6 +10,8 @@
10set(MTP_VERSION_MINOR 0)10set(MTP_VERSION_MINOR 0)
11set(MTP_VERSION_PATCH 0)11set(MTP_VERSION_PATCH 0)
1212
13find_package(Boost REQUIRED COMPONENTS system filesystem unit_test_framework)
14
13set(15set(
14 MTP_HEADERS16 MTP_HEADERS
15 include/MtpDatabase.h17 include/MtpDatabase.h
@@ -53,6 +55,7 @@
53include_directories(55include_directories(
54 include/56 include/
55 libusbhost/include57 libusbhost/include
58 ${Boost_INCLUDE_DIRS}
56)59)
5760
58add_library(61add_library(
@@ -80,5 +83,9 @@
80 PUBLIC_HEADER DESTINATION include/mtp83 PUBLIC_HEADER DESTINATION include/mtp
81)84)
8285
86enable_testing()
87
83add_subdirectory(libusbhost)88add_subdirectory(libusbhost)
84add_subdirectory(examples)89add_subdirectory(server)
90add_subdirectory(tests)
91
8592
=== modified file 'debian/changelog'
--- debian/changelog 2013-06-13 10:22:21 +0000
+++ debian/changelog 2013-09-11 16:32:38 +0000
@@ -1,5 +1,5 @@
1mtp (0.0.1-1) raring; urgency=low1mtp (0.0.1-0ubuntu1) UNRELEASED; urgency=low
22
3 * Initial release3 * Initial release
44
5 -- Thomas Voß <thomas.voss@canonical.com> Mon, 10 June 2013 11:43:05 +02005 -- Mathieu Trudel-Lapierre <mathieu-tl@ubuntu.com> Fri, 06 Sep 2013 16:07:38 -0400
66
=== modified file 'debian/control'
--- debian/control 2013-06-13 10:22:21 +0000
+++ debian/control 2013-09-11 16:32:38 +0000
@@ -1,8 +1,13 @@
1Source: mtp1Source: mtp
2Priority: extra2Section: utils
3Maintainer: Thomas Voß <thomas.voss@canonical.com>3Priority: optional
4Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
5XSBC-Original-Maintainer: Thomas Voß <thomas.voss@canonical.com>
4Build-Depends: debhelper (>= 8.0.0), 6Build-Depends: debhelper (>= 8.0.0),
5 cmake, 7 cmake,
8 libboost-dev,
9 libboost-filesystem-dev,
10 libboost-test-dev,
6Standards-Version: 3.9.411Standards-Version: 3.9.4
7Homepage: http://launchpad.net/mtp12Homepage: http://launchpad.net/mtp
813
@@ -24,12 +29,12 @@
24 .29 .
25 Contains header files required to develop actual services.30 Contains header files required to develop actual services.
2631
27Package: mtp-examples32Package: mtp-server
28Architecture: any33Architecture: any
29Depends: ${misc:Depends},34Depends: ${misc:Depends},
30 ${shlibs:Depends}35 ${shlibs:Depends}
31Description: A server-implementation of MTP.36Description: A server-implementation of MTP.
32 Exposes phone storage over MTP. 37 Exposes phone storage over MTP.
33 .38 .
34 Contains example executables39 Contains a simple MTP server that exposes images, videos, and music.
3540
3641
=== added file 'debian/mtp-server.conf'
--- debian/mtp-server.conf 1970-01-01 00:00:00 +0000
+++ debian/mtp-server.conf 2013-09-11 16:32:38 +0000
@@ -0,0 +1,18 @@
1description "MTP protocol server"
2
3start on :sys:android_usb-device-changed
4
5expect fork
6respawn
7
8pre-start script
9 state=`cat /sys/class/android_usb/android0/state`
10 if [ "$state" = "DISCONNECTED" ]; then
11 stop
12 exit 0
13 fi
14
15 rm -f ~/.cache/upstart/mtp-server.log
16end script
17
18exec /usr/bin/mtp-server &
019
=== renamed file 'debian/mtp-examples.install' => 'debian/mtp-server.install'
--- debian/mtp-examples.install 2013-06-13 10:22:21 +0000
+++ debian/mtp-server.install 2013-09-11 16:32:38 +0000
@@ -1,1 +1,2 @@
1usr/bin/mtp-server
2\ No newline at end of file1\ No newline at end of file
2usr/bin/mtp-server
3debian/mtp-server.conf /usr/share/upstart/sessions/
34
=== added file 'debian/mtp-server.mtp-server-bootup.upstart'
--- debian/mtp-server.mtp-server-bootup.upstart 1970-01-01 00:00:00 +0000
+++ debian/mtp-server.mtp-server-bootup.upstart 2013-09-11 16:32:38 +0000
@@ -0,0 +1,27 @@
1description "MTP protocol server bootup"
2
3start on android
4
5task
6
7emits android_usb-device-changed
8
9script
10 if [ -x /usr/bin/setprop ]; then
11 timeout=10
12 # loop 10 times and then exit, if the property service
13 # isnt up after 80 sec # it is likely not starting at all
14 while [ ! -e /dev/socket/property_service ]; do
15 sleep 8
16 if [ "$timeout" -le 0 ]; then
17 stop
18 exit 0
19 fi
20 timeout=$(($timeout - 1))
21 done
22
23 /usr/bin/setprop sys.usb.config mtp,adb
24 fi
25
26 initctl emit android_usb-device-changed
27end script
028
=== modified file 'debian/rules'
--- debian/rules 2013-06-13 10:22:21 +0000
+++ debian/rules 2013-09-11 16:32:38 +0000
@@ -1,13 +1,11 @@
1#!/usr/bin/make -f1#!/usr/bin/make -f
2# -*- makefile -*-
3# Sample debian/rules that uses debhelper.
4# This file was originally written by Joey Hess and Craig Small.
5# As a special exception, when this file is copied by dh-make into a
6# dh-make output file, you may use that output file without restriction.
7# This special exception was added by Craig Small in version 0.37 of dh-make.
82
9# Uncomment this to turn on verbose mode.3# Uncomment this to turn on verbose mode.
10# export DH_VERBOSE=14# export DH_VERBOSE=1
115
12%:6%:
13 dh $@
14\ No newline at end of file7\ No newline at end of file
8 dh $@
9
10override_dh_installinit:
11 dh_installinit -pmtp-server --name=mtp-server-bootup
12 dh_installinit
1513
=== renamed directory 'examples' => 'server'
=== modified file 'server/CMakeLists.txt'
--- examples/CMakeLists.txt 2013-06-13 10:22:21 +0000
+++ server/CMakeLists.txt 2013-09-11 16:32:38 +0000
@@ -5,13 +5,18 @@
5 server.cpp5 server.cpp
6)6)
77
8set_target_properties(mtp-server PROPERTIES COMPILE_FLAGS -fPIC)
9
8target_link_libraries(10target_link_libraries(
9 mtp-server11 mtp-server
10 mtp12 mtp
11 usbhost13 usbhost
14 ${Boost_LIBRARIES}
15 ${Boost_system_LIBRARIES}
16 ${Boost_filesystem_LIBRARIES}
12)17)
1318
14install(19install(
15 TARGETS mtp-server20 TARGETS mtp-server
16 RUNTIME DESTINATION bin21 RUNTIME DESTINATION bin
17)
18\ No newline at end of file22\ No newline at end of file
23)
1924
=== renamed file 'examples/StubMtpDatabase.h' => 'server/UbuntuMtpDatabase.h'
--- examples/StubMtpDatabase.h 2013-06-13 10:22:21 +0000
+++ server/UbuntuMtpDatabase.h 2013-09-11 16:32:38 +0000
@@ -1,3 +1,19 @@
1/*
2 * Copyright (C) 2013 Canonical Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
1#ifndef STUB_MTP_DATABASE_H_17#ifndef STUB_MTP_DATABASE_H_
2#define STUB_MTP_DATABASE_H_18#define STUB_MTP_DATABASE_H_
319
@@ -7,73 +23,106 @@
7#include <MtpObjectInfo.h>23#include <MtpObjectInfo.h>
8#include <MtpProperty.h>24#include <MtpProperty.h>
925
26#include <cstdlib>
10#include <cstring>27#include <cstring>
11#include <iostream>28#include <iostream>
12#include <map>29#include <map>
30#include <vector>
13#include <string>31#include <string>
14#include <tuple>32#include <tuple>
1533
34#include <boost/foreach.hpp>
35#include <boost/filesystem.hpp>
36#include <boost/range/adaptors.hpp>
37#include <boost/range/algorithm.hpp>
38
39using namespace boost::filesystem;
40
16namespace android41namespace android
17{42{
18class StubMtpDatabase : public android::MtpDatabase {43class UbuntuMtpDatabase : public android::MtpDatabase {
19private:44private:
20 struct DbEntry45 struct DbEntry
21 {46 {
22 MtpStorageID storage_id;47 MtpStorageID storage_id;
23 std::string object_name;48 std::string object_name;
24 MtpObjectFormat object_format;49 MtpObjectFormat object_format;
50 MtpObjectHandle parent;
25 size_t object_size;51 size_t object_size;
26 size_t width;
27 size_t height;
28 size_t bit_depth;
29 std::string display_name;52 std::string display_name;
30 std::string path;53 std::string path;
31 };54 };
3255
33 enum PngImageHandles
34 {
35 png_image_1,
36 png_image_2,
37 png_image_3,
38 png_image_4,
39 png_image_5,
40 png_image_6,
41 png_image_7,
42 png_image_8,
43 png_image_9,
44 png_image_10,
45 png_image_size
46 };
47 static const uint32_t reserved_slots = png_image_size;
48
49 uint32_t counter;56 uint32_t counter;
50 std::map<std::tuple<MtpStorageID, MtpObjectFormat>, MtpObjectHandleList> db = 57 std::map<MtpObjectHandle, DbEntry> db;
58
59 void parse_directory(path p, MtpObjectHandle parent)
51 {60 {
61 DbEntry entry;
62 std::vector<path> v;
63
64 copy(directory_iterator(p), directory_iterator(), std::back_inserter(v));
65
66 for (std::vector<path>::const_iterator it(v.begin()), it_end(v.end()); it != it_end; ++it)
52 {67 {
53 std::make_tuple(MTP_STORAGE_REMOVABLE_RAM, MTP_FORMAT_PNG), 68 MtpObjectHandle handle = counter;
54 {png_image_1, png_image_2, png_image_3, png_image_4, png_image_5, png_image_6, png_image_7, png_image_8, png_image_9, png_image_10}69
70 counter++;
71
72 std::cout << " " << *it << " handle: " << handle << " parent: " << parent << std::endl;
73
74 entry.storage_id = MTP_STORAGE_FIXED_RAM;
75 entry.parent = parent;
76 entry.object_name = it->filename().string();
77 entry.display_name = it->filename().string();
78 entry.path = it->string();
79
80 if (is_regular_file (*it)) {
81 entry.object_format = MTP_FORMAT_DEFINED;
82 entry.object_size = file_size(*it);
83
84 db.insert( std::pair<MtpObjectHandle, DbEntry>(handle, entry) );
85 } else if (is_directory (*it)) {
86 entry.object_format = MTP_FORMAT_ASSOCIATION;
87 entry.object_size = 0;
88
89 db.insert( std::pair<MtpObjectHandle, DbEntry>(handle, entry) );
90
91 parse_directory (*it, handle);
92 }
55 }93 }
56 };94 }
57 95
58 std::map<MtpObjectHandle, DbEntry> entries = 96 void readFiles(const std::string& sourcedir)
59 {97 {
60 {png_image_1, {MTP_STORAGE_REMOVABLE_RAM, "png_image_1", MTP_FORMAT_PNG, 20 * 20 * 4, 20, 20, 4, "png_image_1", "png_image_1.png"}},98 path p (sourcedir);
61 {png_image_2, {MTP_STORAGE_REMOVABLE_RAM, "png_image_2", MTP_FORMAT_PNG, 20 * 20 * 4, 20, 20, 4, "png_image_2", "png_image_2.png"}},99
62 {png_image_3, {MTP_STORAGE_REMOVABLE_RAM, "png_image_3", MTP_FORMAT_PNG, 20 * 20 * 4, 20, 20, 4, "png_image_3", "png_image_3.png"}},100 try {
63 {png_image_4, {MTP_STORAGE_REMOVABLE_RAM, "png_image_4", MTP_FORMAT_PNG, 20 * 20 * 4, 20, 20, 4, "png_image_4", "png_image_4.png"}}, 101 if (exists(p)) {
64 {png_image_5, {MTP_STORAGE_REMOVABLE_RAM, "png_image_5", MTP_FORMAT_PNG, 20 * 20 * 4, 20, 20, 4, "png_image_5", "png_image_5.png"}},102 if (is_directory(p)) {
65 {png_image_6, {MTP_STORAGE_REMOVABLE_RAM, "png_image_6", MTP_FORMAT_PNG, 20 * 20 * 4, 20, 20, 4, "png_image_6", "png_image_6.png"}},103 std::cout << p << " is a directory containing:\n";
66 {png_image_7, {MTP_STORAGE_REMOVABLE_RAM, "png_image_7", MTP_FORMAT_PNG, 20 * 20 * 4, 20, 20, 4, "png_image_7", "png_image_7.png"}},104
67 {png_image_8, {MTP_STORAGE_REMOVABLE_RAM, "png_image_8", MTP_FORMAT_PNG, 20 * 20 * 4, 20, 20, 4, "png_image_8", "png_image_8.png"}},105 parse_directory (p, MTP_PARENT_ROOT);
68 {png_image_9, {MTP_STORAGE_REMOVABLE_RAM, "png_image_9", MTP_FORMAT_PNG, 20 * 20 * 4, 20, 20, 4, "png_image_9", "png_image_9.png"}},106 }
69 {png_image_10, {MTP_STORAGE_REMOVABLE_RAM, "png_image_10", MTP_FORMAT_PNG, 20 * 20 * 4, 20, 20, 4, "png_image_10", "png_image_10.png"}}107 } else
70 };108 std::cout << p << " does not exist\n";
71 109 }
110 catch (const filesystem_error& ex) {
111 std::cout << ex.what() << '\n';
112 }
113
114 }
115
72public:116public:
73 StubMtpDatabase() : counter(StubMtpDatabase::reserved_slots)117 UbuntuMtpDatabase(const char *dir) : counter(1)
74 {118 {
119 db = std::map<MtpObjectHandle, DbEntry>();
120 readFiles(std::string(dir));
121
122 std::cout << __PRETTY_FUNCTION__ << ": object count:" << db.size() << std::endl;
75 }123 }
76 virtual ~StubMtpDatabase() {}124
125 virtual ~UbuntuMtpDatabase() {}
77126
78 // called from SendObjectInfo to reserve a database entry for the incoming file127 // called from SendObjectInfo to reserve a database entry for the incoming file
79 virtual MtpObjectHandle beginSendObject(128 virtual MtpObjectHandle beginSendObject(
@@ -84,8 +133,25 @@
84 uint64_t size,133 uint64_t size,
85 time_t modified)134 time_t modified)
86 {135 {
87 std::cout << __PRETTY_FUNCTION__ << ": " << path << std::endl;136 DbEntry entry;
88 return counter++; 137 MtpObjectHandle handle = counter;
138 MtpObjectHandle parent_id = parent == 0 ? MTP_PARENT_ROOT : parent;
139
140 std::cout << __PRETTY_FUNCTION__ << ": " << path << " - " << parent << std::endl;
141
142 entry.storage_id = storage;
143 entry.parent = parent_id;
144 entry.object_name = std::string(basename(path.c_str()));
145 entry.display_name = std::string(basename(path.c_str()));
146 entry.path = path;
147 entry.object_format = format;
148 entry.object_size = size;
149
150 db.insert( std::pair<MtpObjectHandle, DbEntry>(handle, entry) );
151
152 counter++;
153
154 return handle;
89 }155 }
90156
91 // called to report success or failure of the SendObject file transfer157 // called to report success or failure of the SendObject file transfer
@@ -98,6 +164,10 @@
98 bool succeeded)164 bool succeeded)
99 {165 {
100 std::cout << __PRETTY_FUNCTION__ << ": " << path << std::endl;166 std::cout << __PRETTY_FUNCTION__ << ": " << path << std::endl;
167
168 if (!succeeded) {
169 db.erase(handle);
170 }
101 }171 }
102172
103 virtual MtpObjectHandleList* getObjectList(173 virtual MtpObjectHandleList* getObjectList(
@@ -109,7 +179,14 @@
109 MtpObjectHandleList* list = nullptr;179 MtpObjectHandleList* list = nullptr;
110 try180 try
111 {181 {
112 list = new MtpObjectHandleList(db.at(std::make_tuple(storageID, MTP_FORMAT_PNG)));182 std::vector<MtpObjectHandle> keys;
183
184 BOOST_FOREACH(MtpObjectHandle i, db | boost::adaptors::map_keys) {
185 if (db.at(i).parent == parent)
186 keys.push_back(i);
187 }
188
189 list = new MtpObjectHandleList(keys);
113 } catch(...)190 } catch(...)
114 {191 {
115 list = new MtpObjectHandleList();192 list = new MtpObjectHandleList();
@@ -126,7 +203,7 @@
126 std::cout << __PRETTY_FUNCTION__ << ": " << storageID << ", " << format << ", " << parent << std::endl;203 std::cout << __PRETTY_FUNCTION__ << ": " << storageID << ", " << format << ", " << parent << std::endl;
127 try204 try
128 {205 {
129 return db.at(std::make_tuple(storageID, MTP_FORMAT_PNG)).size();206 return db.size();
130 } catch(...)207 } catch(...)
131 {208 {
132 }209 }
@@ -153,12 +230,15 @@
153 virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format)230 virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format)
154 {231 {
155 std::cout << __PRETTY_FUNCTION__ << std::endl;232 std::cout << __PRETTY_FUNCTION__ << std::endl;
233 /*
156 if (format != MTP_FORMAT_PNG)234 if (format != MTP_FORMAT_PNG)
157 return nullptr;235 return nullptr;
236 */
158 237
159 static const MtpObjectPropertyList list = 238 static const MtpObjectPropertyList list =
160 {239 {
161 MTP_PROPERTY_STORAGE_ID,240 MTP_PROPERTY_STORAGE_ID,
241 MTP_PROPERTY_PARENT_OBJECT,
162 MTP_PROPERTY_OBJECT_FORMAT,242 MTP_PROPERTY_OBJECT_FORMAT,
163 MTP_PROPERTY_OBJECT_SIZE,243 MTP_PROPERTY_OBJECT_SIZE,
164 MTP_PROPERTY_WIDTH,244 MTP_PROPERTY_WIDTH,
@@ -185,13 +265,11 @@
185 std::cout << __PRETTY_FUNCTION__ << std::endl;265 std::cout << __PRETTY_FUNCTION__ << std::endl;
186 switch(property)266 switch(property)
187 {267 {
188 case MTP_PROPERTY_STORAGE_ID: packet.putUInt32(entries.at(handle).storage_id); break; 268 case MTP_PROPERTY_STORAGE_ID: packet.putUInt32(db.at(handle).storage_id); break;
189 case MTP_PROPERTY_OBJECT_FORMAT: packet.putUInt32(entries.at(handle).object_format); break;269 case MTP_PROPERTY_PARENT_OBJECT: packet.putUInt32(db.at(handle).parent); break;
190 case MTP_PROPERTY_OBJECT_SIZE: packet.putUInt32(entries.at(handle).object_size); break;270 case MTP_PROPERTY_OBJECT_FORMAT: packet.putUInt32(db.at(handle).object_format); break;
191 case MTP_PROPERTY_WIDTH: packet.putUInt32(entries.at(handle).width); break;271 case MTP_PROPERTY_OBJECT_SIZE: packet.putUInt32(db.at(handle).object_size); break;
192 case MTP_PROPERTY_HEIGHT: packet.putUInt32(entries.at(handle).height); break;272 case MTP_PROPERTY_DISPLAY_NAME: packet.putString(db.at(handle).display_name.c_str()); break;
193 case MTP_PROPERTY_IMAGE_BIT_DEPTH: packet.putUInt32(entries.at(handle).bit_depth); break;
194 case MTP_PROPERTY_DISPLAY_NAME: packet.putString(entries.at(handle).display_name.c_str()); break;
195 default: return MTP_RESPONSE_GENERAL_ERROR; break; 273 default: return MTP_RESPONSE_GENERAL_ERROR; break;
196 }274 }
197 275
@@ -248,22 +326,22 @@
248 {326 {
249 std::cout << __PRETTY_FUNCTION__ << std::endl;327 std::cout << __PRETTY_FUNCTION__ << std::endl;
250 info.mHandle = handle;328 info.mHandle = handle;
251 info.mStorageID = entries.at(handle).storage_id;329 info.mStorageID = db.at(handle).storage_id;
252 info.mFormat = entries.at(handle).object_format;330 info.mFormat = db.at(handle).object_format;
253 info.mProtectionStatus = 0x0;331 info.mProtectionStatus = 0x0;
254 info.mCompressedSize = 0;332 info.mCompressedSize = 0;
255 info.mThumbFormat = entries.at(handle).object_format;333 info.mThumbFormat = db.at(handle).object_format;
256 info.mThumbCompressedSize = 20*20*4;334 info.mThumbCompressedSize = 20*20*4;
257 info.mThumbPixWidth = 20;335 info.mThumbPixWidth = 20;
258 info.mThumbPixHeight =20;336 info.mThumbPixHeight =20;
259 info.mImagePixWidth = 20;337 info.mImagePixWidth = 20;
260 info.mImagePixHeight = 20;338 info.mImagePixHeight = 20;
261 info.mImagePixDepth = 4;339 info.mImagePixDepth = 4;
262 info.mParent = MTP_PARENT_ROOT;340 info.mParent = db.at(handle).parent;
263 info.mAssociationType = 0;341 info.mAssociationType = 0;
264 info.mAssociationDesc = 0;342 info.mAssociationDesc = 0;
265 info.mSequenceNumber = 0;343 info.mSequenceNumber = 0;
266 info.mName = ::strdup("test");344 info.mName = ::strdup(db.at(handle).object_name.c_str());
267 info.mDateCreated = 0;345 info.mDateCreated = 0;
268 info.mDateModified = 0;346 info.mDateModified = 0;
269 info.mKeywords = ::strdup("ubuntu,touch");347 info.mKeywords = ::strdup("ubuntu,touch");
@@ -273,10 +351,11 @@
273351
274 virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize)352 virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize)
275 {353 {
276 std::cout << __PRETTY_FUNCTION__ << std::endl;354 void* result;
277 outThumbSize = 20*20*4;355
278 void* result = malloc(20*20*4);356 outThumbSize = 0;
279 memset(result, 0, 20*20*4);357 memset(result, 0, outThumbSize);
358
280 return result;359 return result;
281 }360 }
282361
@@ -286,17 +365,61 @@
286 int64_t& outFileLength,365 int64_t& outFileLength,
287 MtpObjectFormat& outFormat)366 MtpObjectFormat& outFormat)
288 {367 {
368 DbEntry entry = db.at(handle);
369
289 std::cout << __PRETTY_FUNCTION__ << std::endl;370 std::cout << __PRETTY_FUNCTION__ << std::endl;
290 outFilePath = entries.at(handle).path;371
291 outFileLength = 1024;372 outFilePath = std::string(entry.path);
292 outFormat = entries.at(handle).object_format;373 outFileLength = entry.object_size;
374 outFormat = entry.object_format;
375
376 return MTP_RESPONSE_OK;
293 }377 }
294378
295 virtual MtpResponseCode deleteFile(MtpObjectHandle handle)379 virtual MtpResponseCode deleteFile(MtpObjectHandle handle)
296 {380 {
297 std::cout << __PRETTY_FUNCTION__ << std::endl;381 size_t orig_size = db.size();
298 return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;382 size_t new_size;
299 }383
384 std::cout << __PRETTY_FUNCTION__ << std::endl;
385
386 new_size = db.erase(handle);
387
388 if (orig_size > new_size) {
389 /* Recursively remove children object from the DB as well.
390 * we can safely ignore failures here, since the objects
391 * would not be reachable anyway.
392 */
393 BOOST_FOREACH(MtpObjectHandle i, db | boost::adaptors::map_keys) {
394 if (db.at(i).parent == handle)
395 db.erase(i);
396 }
397 return MTP_RESPONSE_OK;
398 }
399 else
400 return MTP_RESPONSE_GENERAL_ERROR;
401 }
402
403 /*
404 virtual MtpResponseCode moveFile(MtpObjectHandle handle, MtpObjectHandle new_parent)
405 {
406 std::cout << __PRETTY_FUNCTION__ << std::endl;
407
408 // change parent
409
410 return MTP_RESPONSE_OK
411 }
412
413 virtual MtpResponseCode copyFile(MtpObjectHandle handle, MtpObjectHandle new_parent)
414 {
415 std::cout << __PRETTY_FUNCTION__ << std::endl;
416
417 // duplicate DbEntry
418 // change parent
419
420 return MTP_RESPONSE_OK
421 }
422 */
300423
301 virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle)424 virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle)
302 {425 {
303426
=== modified file 'server/server.cpp'
--- examples/server.cpp 2013-06-13 10:22:21 +0000
+++ server/server.cpp 2013-09-11 16:32:38 +0000
@@ -1,4 +1,20 @@
1#include "StubMtpDatabase.h"1/*
2 * Copyright (C) 2013 Canonical Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "UbuntuMtpDatabase.h"
218
3#include <MtpServer.h>19#include <MtpServer.h>
4#include <MtpStorage.h>20#include <MtpStorage.h>
@@ -10,27 +26,23 @@
10#include <sys/stat.h>26#include <sys/stat.h>
11#include <fcntl.h>27#include <fcntl.h>
12#include <unistd.h>28#include <unistd.h>
29#include <pwd.h>
1330
14namespace31namespace
15{32{
16struct FileSystemConfig33struct FileSystemConfig
17{34{
18 static const int file_group = 1023; // Taken from android's config. Might need to be adjusted.
19 static const int file_perm = 0664;35 static const int file_perm = 0664;
20 static const int directory_perm = 0755;36 static const int directory_perm = 0755;
21};37};
2238
23android::MtpStorage* removable_storage = new android::MtpStorage(39android::MtpStorage* home_storage;
24 MTP_STORAGE_REMOVABLE_RAM, 40
25 ".",
26 "Dummy storage",
27 1024 * 1024 * 1024 * 200,
28 true,
29 1024 * 1024 * 1024);
30}41}
3142
32int main(int argc, char** argv)43int main(int argc, char** argv)
33{44{
45 struct passwd *userdata = getpwuid (getuid());
34 int fd = open("/dev/mtp_usb", O_RDWR);46 int fd = open("/dev/mtp_usb", O_RDWR);
35 47
36 if (fd < 0)48 if (fd < 0)
@@ -38,17 +50,25 @@
38 std::cout << "Error opening /dev/mtp_usb, aborting now..." << std::endl;50 std::cout << "Error opening /dev/mtp_usb, aborting now..." << std::endl;
39 }51 }
40 52
53 home_storage = new android::MtpStorage(
54 MTP_STORAGE_FIXED_RAM,
55 userdata->pw_dir,
56 userdata->pw_name,
57 1024 * 1024 * 100, /* 100 MB reserved space, to avoid filling the disk */
58 false,
59 1024 * 1024 * 1024 * 2 /* 2GB arbitrary max file size */);
60
41 std::shared_ptr<android::MtpServer> server61 std::shared_ptr<android::MtpServer> server
42 {62 {
43 new android::MtpServer(63 new android::MtpServer(
44 fd, 64 fd,
45 new android::StubMtpDatabase(),65 new android::UbuntuMtpDatabase(userdata->pw_dir),
46 false, 66 false,
47 FileSystemConfig::file_group, 67 userdata->pw_gid,
48 FileSystemConfig::file_perm, 68 FileSystemConfig::file_perm,
49 FileSystemConfig::directory_perm)69 FileSystemConfig::directory_perm)
50 };70 };
51 server->addStorage(removable_storage);71 server->addStorage(home_storage);
52 server->run();72 server->run();
5373
54 /*74 /*
5575
=== modified file 'src/MtpUtils.cpp'
--- src/MtpUtils.cpp 2013-06-13 10:22:21 +0000
+++ src/MtpUtils.cpp 2013-09-11 16:32:38 +0000
@@ -49,6 +49,7 @@
4949
50 // hack to compute timezone50 // hack to compute timezone
51 time_t dummy;51 time_t dummy;
52 tzset();
52 localtime_r(&dummy, &tm);53 localtime_r(&dummy, &tm);
5354
54 tm.tm_sec = second;55 tm.tm_sec = second;
5556
=== added directory 'tests'
=== added file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ tests/CMakeLists.txt 2013-09-11 16:32:38 +0000
@@ -0,0 +1,91 @@
1
2# MtpUtils
3add_executable(
4 test-utils
5 TestMtpUtils.cpp
6)
7
8target_link_libraries(
9 test-utils
10 mtp
11 usbhost
12 ${Boost_LIBRARIES}
13 ${Boost_unit_test_framework_LIBRARIES}
14)
15add_test(test-utils test-utils)
16
17# MtpDebug
18add_executable(
19 test-debug
20 TestMtpDebug.cpp
21)
22
23target_link_libraries(
24 test-debug
25 mtp
26 usbhost
27 ${Boost_LIBRARIES}
28 ${Boost_unit_test_framework_LIBRARIES}
29)
30add_test(test-debug test-debug)
31
32# MtpPacket
33add_executable(
34 test-packet
35 TestMtpPacket.cpp
36)
37
38target_link_libraries(
39 test-packet
40 mtp
41 usbhost
42 ${Boost_LIBRARIES}
43 ${Boost_unit_test_framework_LIBRARIES}
44)
45add_test(test-packet test-packet)
46
47# MtpProperty
48add_executable(
49 test-property
50 TestMtpProperty.cpp
51)
52
53target_link_libraries(
54 test-property
55 mtp
56 usbhost
57 ${Boost_LIBRARIES}
58 ${Boost_unit_test_framework_LIBRARIES}
59)
60add_test(test-property test-property)
61
62# MtpStorage
63add_executable(
64 test-storage
65 TestMtpStorage.cpp
66)
67
68target_link_libraries(
69 test-storage
70 mtp
71 usbhost
72 ${Boost_LIBRARIES}
73 ${Boost_unit_test_framework_LIBRARIES}
74)
75add_test(test-storage test-storage)
76
77# MtpServer
78add_executable(
79 test-server
80 TestMtpServer.cpp
81)
82
83target_link_libraries(
84 test-server
85 mtp
86 usbhost
87 ${Boost_LIBRARIES}
88 ${Boost_unit_test_framework_LIBRARIES}
89)
90add_test(test-server test-server)
91
092
=== added file 'tests/MockMtpDatabase.h'
--- tests/MockMtpDatabase.h 1970-01-01 00:00:00 +0000
+++ tests/MockMtpDatabase.h 2013-09-11 16:32:38 +0000
@@ -0,0 +1,358 @@
1/*
2 * Copyright (C) 2013 Canonical Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef STUB_MOCK_MTP_DATABASE_H_
18#define STUB_MOCK_MTP_DATABASE_H_
19
20#include <mtp.h>
21#include <MtpDatabase.h>
22#include <MtpDataPacket.h>
23#include <MtpObjectInfo.h>
24#include <MtpProperty.h>
25
26#include <cstdlib>
27#include <cstring>
28#include <iostream>
29#include <map>
30#include <vector>
31#include <string>
32#include <tuple>
33
34#include <boost/foreach.hpp>
35#include <boost/filesystem.hpp>
36#include <boost/range/adaptors.hpp>
37#include <boost/range/algorithm.hpp>
38
39namespace android
40{
41class MockMtpDatabase : public android::MtpDatabase {
42private:
43 struct DbEntry
44 {
45 MtpStorageID storage_id;
46 std::string object_name;
47 MtpObjectFormat object_format;
48 MtpObjectHandle parent;
49 size_t object_size;
50 std::string display_name;
51 std::string path;
52 };
53
54 uint32_t counter;
55 std::map<MtpObjectHandle, DbEntry> db;
56
57public:
58 MockMtpDatabase() : counter(1)
59 {
60 DbEntry entry;
61 db = std::map<MtpObjectHandle, DbEntry>();
62
63 entry.storage_id = 666;
64 entry.object_name = std::string("Test Object");
65 entry.object_format = MTP_FORMAT_PNG;
66 entry.parent = MTP_PARENT_ROOT;
67 entry.object_size = 666;
68 entry.display_name = std::string("Test Object");
69 entry.path = std::string("TestObject");
70
71 db.insert( std::pair<MtpObjectHandle, DbEntry>(counter, entry) );
72 }
73
74 virtual ~MockMtpDatabase() {}
75
76 virtual MtpObjectHandle beginSendObject(
77 const MtpString& path,
78 MtpObjectFormat format,
79 MtpObjectHandle parent,
80 MtpStorageID storage,
81 uint64_t size,
82 time_t modified)
83 {
84 return 1;
85 }
86
87 virtual void endSendObject(
88 const MtpString& path,
89 MtpObjectHandle handle,
90 MtpObjectFormat format,
91 bool succeeded)
92 {
93 std::cout << __PRETTY_FUNCTION__ << ": " << path << std::endl;
94
95 if (!succeeded) {
96 db.erase(handle);
97 }
98 }
99
100 virtual MtpObjectHandleList* getObjectList(
101 MtpStorageID storageID,
102 MtpObjectFormat format,
103 MtpObjectHandle parent)
104 {
105 MtpObjectHandleList* list = nullptr;
106
107 if (db.empty()) {
108 list = new MtpObjectHandleList();
109 } else {
110 std::vector<MtpObjectHandle> keys;
111 keys.push_back(1);
112 list = new MtpObjectHandleList(keys);
113 }
114
115 return list;
116 }
117
118 virtual int getNumObjects(
119 MtpStorageID storageID,
120 MtpObjectFormat format,
121 MtpObjectHandle parent)
122 {
123 return db.size();
124 }
125
126 virtual MtpObjectFormatList* getSupportedPlaybackFormats()
127 {
128 std::cout << __PRETTY_FUNCTION__ << std::endl;
129 static const MtpObjectFormatList list = {MTP_FORMAT_PNG};
130 return new MtpObjectFormatList{list};
131 }
132
133 virtual MtpObjectFormatList* getSupportedCaptureFormats()
134 {
135 std::cout << __PRETTY_FUNCTION__ << std::endl;
136 static const MtpObjectFormatList list = {MTP_FORMAT_ASSOCIATION, MTP_FORMAT_PNG};
137 return new MtpObjectFormatList{list};
138 }
139
140 virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format)
141 {
142 std::cout << __PRETTY_FUNCTION__ << std::endl;
143
144 static const MtpObjectPropertyList list =
145 {
146 MTP_PROPERTY_STORAGE_ID,
147 MTP_PROPERTY_PARENT_OBJECT,
148 MTP_PROPERTY_OBJECT_FORMAT,
149 MTP_PROPERTY_OBJECT_SIZE,
150 MTP_PROPERTY_WIDTH,
151 MTP_PROPERTY_HEIGHT,
152 MTP_PROPERTY_IMAGE_BIT_DEPTH,
153 MTP_PROPERTY_DISPLAY_NAME
154 };
155
156 return new MtpObjectPropertyList{list};
157 }
158
159 virtual MtpDevicePropertyList* getSupportedDeviceProperties()
160 {
161 std::cout << __PRETTY_FUNCTION__ << std::endl;
162 static const MtpDevicePropertyList list = { MTP_DEVICE_PROPERTY_UNDEFINED };
163 return new MtpDevicePropertyList{list};
164 }
165
166 virtual MtpResponseCode getObjectPropertyValue(
167 MtpObjectHandle handle,
168 MtpObjectProperty property,
169 MtpDataPacket& packet)
170 {
171 std::cout << __PRETTY_FUNCTION__ << std::endl;
172 switch(property)
173 {
174 case MTP_PROPERTY_STORAGE_ID: packet.putUInt32(db.at(handle).storage_id); break;
175 case MTP_PROPERTY_PARENT_OBJECT: packet.putUInt32(db.at(handle).parent); break;
176 case MTP_PROPERTY_OBJECT_FORMAT: packet.putUInt32(db.at(handle).object_format); break;
177 case MTP_PROPERTY_OBJECT_SIZE: packet.putUInt32(db.at(handle).object_size); break;
178 case MTP_PROPERTY_DISPLAY_NAME: packet.putString(db.at(handle).display_name.c_str()); break;
179 default: return MTP_RESPONSE_GENERAL_ERROR; break;
180 }
181
182 return MTP_RESPONSE_OK;
183 }
184
185 virtual MtpResponseCode setObjectPropertyValue(
186 MtpObjectHandle handle,
187 MtpObjectProperty property,
188 MtpDataPacket& packet)
189 {
190 std::cout << __PRETTY_FUNCTION__ << std::endl;
191 return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
192 }
193
194 virtual MtpResponseCode getDevicePropertyValue(
195 MtpDeviceProperty property,
196 MtpDataPacket& packet)
197 {
198 std::cout << __PRETTY_FUNCTION__ << std::endl;
199 return MTP_RESPONSE_GENERAL_ERROR;
200 }
201
202 virtual MtpResponseCode setDevicePropertyValue(
203 MtpDeviceProperty property,
204 MtpDataPacket& packet)
205 {
206 std::cout << __PRETTY_FUNCTION__ << std::endl;
207 return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
208 }
209
210 virtual MtpResponseCode resetDeviceProperty(
211 MtpDeviceProperty property)
212 {
213 std::cout << __PRETTY_FUNCTION__ << std::endl;
214 return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
215 }
216
217 virtual MtpResponseCode getObjectPropertyList(
218 MtpObjectHandle handle,
219 uint32_t format,
220 uint32_t property,
221 int groupCode,
222 int depth,
223 MtpDataPacket& packet)
224 {
225 std::cout << __PRETTY_FUNCTION__ << std::endl;
226 return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
227 }
228
229 virtual MtpResponseCode getObjectInfo(
230 MtpObjectHandle handle,
231 MtpObjectInfo& info)
232 {
233 std::cout << __PRETTY_FUNCTION__ << std::endl;
234 info.mHandle = handle;
235 info.mStorageID = db.at(handle).storage_id;
236 info.mFormat = db.at(handle).object_format;
237 info.mProtectionStatus = 0x0;
238 info.mCompressedSize = 0;
239 info.mThumbFormat = db.at(handle).object_format;
240 info.mThumbCompressedSize = 20*20*4;
241 info.mThumbPixWidth = 20;
242 info.mThumbPixHeight =20;
243 info.mImagePixWidth = 20;
244 info.mImagePixHeight = 20;
245 info.mImagePixDepth = 4;
246 info.mParent = db.at(handle).parent;
247 info.mAssociationType = 0;
248 info.mAssociationDesc = 0;
249 info.mSequenceNumber = 0;
250 info.mName = ::strdup(db.at(handle).object_name.c_str());
251 info.mDateCreated = 0;
252 info.mDateModified = 0;
253 info.mKeywords = ::strdup("test");
254
255 return MTP_RESPONSE_OK;
256 }
257
258 virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize)
259 {
260 void* result;
261
262 outThumbSize = 0;
263 memset(result, 0, outThumbSize);
264
265 return result;
266 }
267
268 virtual MtpResponseCode getObjectFilePath(
269 MtpObjectHandle handle,
270 MtpString& outFilePath,
271 int64_t& outFileLength,
272 MtpObjectFormat& outFormat)
273 {
274 DbEntry entry = db.at(handle);
275
276 std::cout << __PRETTY_FUNCTION__ << std::endl;
277
278 outFilePath = std::string(entry.path);
279 outFileLength = entry.object_size;
280 outFormat = entry.object_format;
281
282 return MTP_RESPONSE_OK;
283 }
284
285 virtual MtpResponseCode deleteFile(MtpObjectHandle handle)
286 {
287 size_t orig_size = db.size();
288 size_t new_size;
289
290 std::cout << __PRETTY_FUNCTION__ << std::endl;
291
292 new_size = db.erase(handle);
293
294 if (orig_size > new_size) {
295 BOOST_FOREACH(MtpObjectHandle i, db | boost::adaptors::map_keys) {
296 if (db.at(i).parent == handle)
297 db.erase(i);
298 }
299 return MTP_RESPONSE_OK;
300 }
301 else
302 return MTP_RESPONSE_GENERAL_ERROR;
303 }
304
305 virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle)
306 {
307 std::cout << __PRETTY_FUNCTION__ << std::endl;
308 return nullptr;
309 }
310
311 virtual MtpResponseCode setObjectReferences(
312 MtpObjectHandle handle,
313 MtpObjectHandleList* references)
314 {
315 std::cout << __PRETTY_FUNCTION__ << std::endl;
316 return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
317 }
318
319 virtual MtpProperty* getObjectPropertyDesc(
320 MtpObjectProperty property,
321 MtpObjectFormat format)
322 {
323 std::cout << __PRETTY_FUNCTION__ << std::endl;
324 MtpProperty* result = nullptr;
325 switch(property)
326 {
327 case MTP_PROPERTY_STORAGE_ID: result = new MtpProperty(property, MTP_TYPE_UINT32); break;
328 case MTP_PROPERTY_OBJECT_FORMAT: result = new MtpProperty(property, MTP_TYPE_UINT32); break;
329 case MTP_PROPERTY_OBJECT_SIZE: result = new MtpProperty(property, MTP_TYPE_UINT32); break;
330 case MTP_PROPERTY_WIDTH: result = new MtpProperty(property, MTP_TYPE_UINT32); break;
331 case MTP_PROPERTY_HEIGHT: result = new MtpProperty(property, MTP_TYPE_UINT32); break;
332 case MTP_PROPERTY_IMAGE_BIT_DEPTH: result = new MtpProperty(property, MTP_TYPE_UINT32); break;
333 case MTP_PROPERTY_DISPLAY_NAME: result = new MtpProperty(property, MTP_TYPE_STR); break;
334 default: break;
335 }
336
337 return result;
338 }
339
340 virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property)
341 {
342 std::cout << __PRETTY_FUNCTION__ << std::endl;
343 return new MtpProperty(MTP_DEVICE_PROPERTY_UNDEFINED, MTP_TYPE_UNDEFINED);
344 }
345
346 virtual void sessionStarted()
347 {
348 std::cout << __PRETTY_FUNCTION__ << std::endl;
349 }
350
351 virtual void sessionEnded()
352 {
353 std::cout << __PRETTY_FUNCTION__ << std::endl;
354 }
355};
356}
357
358#endif // STUB_MOCK_MTP_DATABASE_H_
0359
=== added file 'tests/TestMtpDebug.cpp'
--- tests/TestMtpDebug.cpp 1970-01-01 00:00:00 +0000
+++ tests/TestMtpDebug.cpp 2013-09-11 16:32:38 +0000
@@ -0,0 +1,49 @@
1/*
2 * Copyright (C) 2013 Canonical Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define BOOST_TEST_DYN_LINK
18#define BOOST_TEST_MAIN
19#include <boost/test/unit_test.hpp>
20
21#include "mtp.h"
22#include "MtpDebug.h"
23
24using namespace android;
25
26BOOST_AUTO_TEST_CASE(DebugGetOperationCodeName)
27{
28 BOOST_CHECK_EQUAL( MtpDebug::getOperationCodeName(MTP_OPERATION_GET_DEVICE_INFO), "MTP_OPERATION_GET_DEVICE_INFO" );
29}
30
31BOOST_AUTO_TEST_CASE(DebugGetFormatCodeName)
32{
33 BOOST_CHECK_EQUAL( MtpDebug::getFormatCodeName(MTP_FORMAT_PNG), "MTP_FORMAT_PNG" );
34}
35
36BOOST_AUTO_TEST_CASE(DebugGetObjectPropCodeName)
37{
38 BOOST_CHECK_EQUAL( MtpDebug::getObjectPropCodeName(MTP_PROPERTY_STORAGE_ID), "MTP_PROPERTY_STORAGE_ID" );
39}
40
41BOOST_AUTO_TEST_CASE(DebugGetDevicePropCodeName)
42{
43 BOOST_CHECK_EQUAL( MtpDebug::getDevicePropCodeName(MTP_DEVICE_PROPERTY_BATTERY_LEVEL), "MTP_DEVICE_PROPERTY_BATTERY_LEVEL" );
44}
45
46BOOST_AUTO_TEST_CASE(DebugGetCodeNameUnknown)
47{
48 BOOST_CHECK_EQUAL( MtpDebug::getOperationCodeName (1), "UNKNOWN");
49}
050
=== added file 'tests/TestMtpPacket.cpp'
--- tests/TestMtpPacket.cpp 1970-01-01 00:00:00 +0000
+++ tests/TestMtpPacket.cpp 2013-09-11 16:32:38 +0000
@@ -0,0 +1,50 @@
1/*
2 * Copyright (C) 2013 Canonical Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define BOOST_TEST_DYN_LINK
18#define BOOST_TEST_MAIN
19#include <boost/test/unit_test.hpp>
20
21#include "mtp.h"
22#include "MtpPacket.h"
23
24using namespace android;
25
26BOOST_AUTO_TEST_CASE(Packet)
27{
28 MtpPacket *p = new MtpPacket (4);
29
30 BOOST_REQUIRE(p);
31}
32
33BOOST_AUTO_TEST_CASE(PacketReset)
34{
35 MtpPacket *p = new MtpPacket (MTP_CONTAINER_PARAMETER_OFFSET + 4);
36 uint32_t value = UINT32_MAX;
37 uint32_t result;
38
39 BOOST_REQUIRE(p);
40
41 p->setParameter(1, value);
42 result = p->getParameter(1);
43 BOOST_CHECK_EQUAL (value, result);
44
45 p->reset();
46
47 result = p->getParameter(1);
48 BOOST_CHECK (value != result);
49 BOOST_CHECK (result == 0);
50}
051
=== added file 'tests/TestMtpProperty.cpp'
--- tests/TestMtpProperty.cpp 1970-01-01 00:00:00 +0000
+++ tests/TestMtpProperty.cpp 2013-09-11 16:32:38 +0000
@@ -0,0 +1,95 @@
1/*
2 * Copyright (C) 2013 Canonical Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define BOOST_TEST_DYN_LINK
18#define BOOST_TEST_MAIN
19#include <boost/test/unit_test.hpp>
20
21#include "mtp.h"
22#include "MtpProperty.h"
23#include "MtpStringBuffer.h"
24
25using namespace android;
26
27BOOST_AUTO_TEST_CASE(PropertyConstructorString)
28{
29 MtpProperty *prop = new MtpProperty(MTP_PROPERTY_NAME, MTP_TYPE_STR, false);
30
31 BOOST_CHECK (prop);
32 BOOST_CHECK (prop->mType == MTP_TYPE_STR);
33 BOOST_CHECK (prop->mCode == MTP_PROPERTY_NAME);
34 BOOST_CHECK (prop->mWriteable == false);
35
36 BOOST_CHECK (prop->mDefaultValue.u.u64 == 0);
37 BOOST_CHECK (prop->mCurrentValue.u.u64 == 0);
38}
39
40BOOST_AUTO_TEST_CASE(PropertyConstructorUInt32)
41{
42 MtpProperty *prop = new MtpProperty(MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32, true, 42);
43
44 BOOST_CHECK (prop);
45 BOOST_CHECK (prop->mType == MTP_TYPE_UINT32);
46 BOOST_CHECK (prop->mCode == MTP_PROPERTY_STORAGE_ID);
47 BOOST_CHECK (prop->mWriteable == true);
48
49 BOOST_CHECK (prop->mDefaultValue.u.u32 == 42);
50 BOOST_CHECK (prop->mCurrentValue.u.u64 == 0);
51}
52
53BOOST_AUTO_TEST_CASE(PropertySetFormRange)
54{
55 MtpProperty *prop = new MtpProperty(MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32, true, 42);
56
57 prop->setFormRange(0, 90, 2);
58
59 BOOST_CHECK(prop->mMinimumValue.u.u32 == 0);
60 BOOST_CHECK(prop->mMaximumValue.u.u32 == 90);
61 BOOST_CHECK(prop->mStepSize.u.u32 == 2);
62}
63
64BOOST_AUTO_TEST_CASE(PropertySetFormEnum)
65{
66 MtpProperty *prop = new MtpProperty(MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32, true, 42);
67 const int values[4] = { 1, 2, 3, 4, };
68
69 prop->setFormEnum(values, 4);
70
71 BOOST_CHECK(prop->mEnumValues[0].u.u32 == 1);
72 BOOST_CHECK(prop->mEnumValues[1].u.u32 == 2);
73 BOOST_CHECK(prop->mEnumValues[2].u.u32 == 3);
74 BOOST_CHECK(prop->mEnumValues[3].u.u32 == 4);
75}
76
77BOOST_AUTO_TEST_CASE(PropertySetFormDateTime)
78{
79 MtpProperty *prop = new MtpProperty(MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32, true, 42);
80
81 prop->setFormDateTime();
82
83 BOOST_CHECK(prop->mFormFlag == MtpProperty::kFormDateTime);
84}
85
86BOOST_AUTO_TEST_CASE(PropertyPrintToBuffer)
87{
88 MtpProperty *prop = new MtpProperty(MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32, true, 42);
89 std::string expected ("42");
90 std::string result;
91
92 prop->print(prop->mDefaultValue, result);
93
94 BOOST_CHECK (result == expected);
95}
096
=== added file 'tests/TestMtpServer.cpp'
--- tests/TestMtpServer.cpp 1970-01-01 00:00:00 +0000
+++ tests/TestMtpServer.cpp 2013-09-11 16:32:38 +0000
@@ -0,0 +1,72 @@
1/*
2 * Copyright (C) 2013 Canonical Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define BOOST_TEST_DYN_LINK
18#define BOOST_TEST_MAIN
19#include <boost/test/unit_test.hpp>
20
21#include "mtp.h"
22#include "MockMtpDatabase.h"
23#include "MtpServer.h"
24#include "MtpStorage.h"
25
26using namespace android;
27
28BOOST_AUTO_TEST_CASE(ServerConstructor)
29{
30 MtpDatabase *db = new MockMtpDatabase ();
31 MtpServer *server = new MtpServer (0, db, false, 0, 0, 0);
32
33 BOOST_CHECK(server);
34}
35
36BOOST_AUTO_TEST_CASE(ServerAddGetStorage)
37{
38 MtpDatabase *db = new MockMtpDatabase ();
39 MtpServer *server = new MtpServer (0, db, false, 0, 0, 0);
40 MtpStorage *storage = new MtpStorage (666, "/tmp", "Test storage", 0, false, 64);
41
42 server->addStorage(storage);
43
44 BOOST_CHECK(server->getStorage(666) != NULL);
45}
46
47BOOST_AUTO_TEST_CASE(ServerGetStorageNull)
48{
49 MtpDatabase *db = new MockMtpDatabase ();
50 MtpServer *server = new MtpServer (0, db, false, 0, 0, 0);
51
52 BOOST_CHECK(server->getStorage(666) == NULL);
53}
54
55BOOST_AUTO_TEST_CASE(ServerHasStorageTrue)
56{
57 MtpDatabase *db = new MockMtpDatabase ();
58 MtpServer *server = new MtpServer (0, db, false, 0, 0, 0);
59 MtpStorage *storage = new MtpStorage (666, "/tmp", "Test storage", 0, false, 64);
60
61 server->addStorage(storage);
62
63 BOOST_CHECK(server->hasStorage(666));
64}
65
66BOOST_AUTO_TEST_CASE(ServerHasStorageFalse)
67{
68 MtpDatabase *db = new MockMtpDatabase ();
69 MtpServer *server = new MtpServer (0, db, false, 0, 0, 0);
70
71 BOOST_CHECK(server->hasStorage(667) == false);
72}
073
=== added file 'tests/TestMtpStorage.cpp'
--- tests/TestMtpStorage.cpp 1970-01-01 00:00:00 +0000
+++ tests/TestMtpStorage.cpp 2013-09-11 16:32:38 +0000
@@ -0,0 +1,87 @@
1/*
2 * Copyright (C) 2013 Canonical Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define BOOST_TEST_DYN_LINK
18#define BOOST_TEST_MAIN
19#include <boost/test/unit_test.hpp>
20
21#include "mtp.h"
22#include "MtpStorage.h"
23
24using namespace android;
25
26BOOST_AUTO_TEST_CASE(StorageConstructor)
27{
28 MtpStorage *s = new MtpStorage (666, "/tmp", "Test storage", 0, false, 64);
29
30 BOOST_CHECK(s);
31}
32
33BOOST_AUTO_TEST_CASE(StorageGetTypeFixed)
34{
35 MtpStorage *s = new MtpStorage (666, "/tmp", "Test storage", 0, false, 64);
36
37 BOOST_CHECK (s->getType() == MTP_STORAGE_FIXED_RAM);
38}
39
40BOOST_AUTO_TEST_CASE(StorageGetTypeRemovable)
41{
42 MtpStorage *s = new MtpStorage (666, "/tmp", "Test storage", 0, true, 64);
43
44 BOOST_CHECK (s->getType() == MTP_STORAGE_REMOVABLE_RAM);
45}
46
47BOOST_AUTO_TEST_CASE(StorageGetFileSystemType)
48{
49 MtpStorage *s = new MtpStorage (666, "/tmp", "Test storage", 0, true, 64);
50
51 BOOST_CHECK (s->getFileSystemType() == MTP_STORAGE_FILESYSTEM_HIERARCHICAL);
52}
53
54BOOST_AUTO_TEST_CASE(StorageGetAccessCapa)
55{
56 MtpStorage *s = new MtpStorage (666, "/tmp", "Test storage", 0, true, 64);
57
58 BOOST_CHECK (s->getAccessCapability() == MTP_STORAGE_READ_WRITE);
59}
60
61BOOST_AUTO_TEST_CASE(StorageGetMaxCapacity)
62{
63 MtpStorage *s = new MtpStorage (666, "/tmp", "Test storage", 0, true, 64);
64
65 BOOST_CHECK (s->getMaxCapacity() > 0);
66}
67
68BOOST_AUTO_TEST_CASE(StorageGetMaxCapacityInvalidPath)
69{
70 MtpStorage *s = new MtpStorage (666, "", "Test storage", 0, true, 64);
71
72 BOOST_CHECK (s->getMaxCapacity() == -1);
73}
74
75BOOST_AUTO_TEST_CASE(StoageGetFreeSpace)
76{
77 MtpStorage *s = new MtpStorage (666, "/", "Test storage", 0, true, 64);
78
79 BOOST_CHECK (s->getFreeSpace() != -1);
80}
81
82BOOST_AUTO_TEST_CASE(StorageGetDescription)
83{
84 MtpStorage *s = new MtpStorage (666, "/", "Test storage", 0, true, 64);
85
86 BOOST_CHECK_EQUAL( strcmp( s->getDescription(), "Test storage" ), 0);
87}
088
=== added file 'tests/TestMtpUtils.cpp'
--- tests/TestMtpUtils.cpp 1970-01-01 00:00:00 +0000
+++ tests/TestMtpUtils.cpp 2013-09-11 16:32:38 +0000
@@ -0,0 +1,48 @@
1/*
2 * Copyright (C) 2013 Canonical Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define BOOST_TEST_DYN_LINK
18#define BOOST_TEST_MAIN
19#include <boost/test/unit_test.hpp>
20
21#include <cstdlib>
22
23// #include <cutils/tztime.h>
24#include "MtpUtils.h"
25
26using namespace android;
27
28BOOST_AUTO_TEST_CASE(UtilsParseDateTime)
29{
30 time_t seconds;
31
32 setenv("TZ", "UTC", 1);
33
34 parseDateTime("20130909T114143", seconds);
35 BOOST_CHECK_EQUAL(seconds, 1378726903l);
36}
37
38BOOST_AUTO_TEST_CASE(UtilsFormatDateTime)
39{
40 time_t seconds = 1378726903;
41 char buffer[25];
42 char *expected = "20130909T114143";
43
44 setenv("TZ", "UTC", 1);
45
46 formatDateTime(seconds, buffer, 25);
47 BOOST_CHECK_EQUAL(strcmp(expected, buffer), 0);
48}

Subscribers

People subscribed via source and target branches