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
1=== added directory '.bzr-builddeb'
2=== added file '.bzr-builddeb/default.conf'
3--- .bzr-builddeb/default.conf 1970-01-01 00:00:00 +0000
4+++ .bzr-builddeb/default.conf 2013-09-11 16:32:38 +0000
5@@ -0,0 +1,2 @@
6+[BUILDDEB]
7+split = True
8
9=== modified file 'CMakeLists.txt'
10--- CMakeLists.txt 2013-06-13 10:22:21 +0000
11+++ CMakeLists.txt 2013-09-11 16:32:38 +0000
12@@ -10,6 +10,8 @@
13 set(MTP_VERSION_MINOR 0)
14 set(MTP_VERSION_PATCH 0)
15
16+find_package(Boost REQUIRED COMPONENTS system filesystem unit_test_framework)
17+
18 set(
19 MTP_HEADERS
20 include/MtpDatabase.h
21@@ -53,6 +55,7 @@
22 include_directories(
23 include/
24 libusbhost/include
25+ ${Boost_INCLUDE_DIRS}
26 )
27
28 add_library(
29@@ -80,5 +83,9 @@
30 PUBLIC_HEADER DESTINATION include/mtp
31 )
32
33+enable_testing()
34+
35 add_subdirectory(libusbhost)
36-add_subdirectory(examples)
37+add_subdirectory(server)
38+add_subdirectory(tests)
39+
40
41=== modified file 'debian/changelog'
42--- debian/changelog 2013-06-13 10:22:21 +0000
43+++ debian/changelog 2013-09-11 16:32:38 +0000
44@@ -1,5 +1,5 @@
45-mtp (0.0.1-1) raring; urgency=low
46+mtp (0.0.1-0ubuntu1) UNRELEASED; urgency=low
47
48 * Initial release
49
50- -- Thomas Voß <thomas.voss@canonical.com> Mon, 10 June 2013 11:43:05 +0200
51+ -- Mathieu Trudel-Lapierre <mathieu-tl@ubuntu.com> Fri, 06 Sep 2013 16:07:38 -0400
52
53=== modified file 'debian/control'
54--- debian/control 2013-06-13 10:22:21 +0000
55+++ debian/control 2013-09-11 16:32:38 +0000
56@@ -1,8 +1,13 @@
57 Source: mtp
58-Priority: extra
59-Maintainer: Thomas Voß <thomas.voss@canonical.com>
60+Section: utils
61+Priority: optional
62+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
63+XSBC-Original-Maintainer: Thomas Voß <thomas.voss@canonical.com>
64 Build-Depends: debhelper (>= 8.0.0),
65- cmake,
66+ cmake,
67+ libboost-dev,
68+ libboost-filesystem-dev,
69+ libboost-test-dev,
70 Standards-Version: 3.9.4
71 Homepage: http://launchpad.net/mtp
72
73@@ -24,12 +29,12 @@
74 .
75 Contains header files required to develop actual services.
76
77-Package: mtp-examples
78+Package: mtp-server
79 Architecture: any
80 Depends: ${misc:Depends},
81 ${shlibs:Depends}
82 Description: A server-implementation of MTP.
83 Exposes phone storage over MTP.
84 .
85- Contains example executables
86+ Contains a simple MTP server that exposes images, videos, and music.
87
88
89=== added file 'debian/mtp-server.conf'
90--- debian/mtp-server.conf 1970-01-01 00:00:00 +0000
91+++ debian/mtp-server.conf 2013-09-11 16:32:38 +0000
92@@ -0,0 +1,18 @@
93+description "MTP protocol server"
94+
95+start on :sys:android_usb-device-changed
96+
97+expect fork
98+respawn
99+
100+pre-start script
101+ state=`cat /sys/class/android_usb/android0/state`
102+ if [ "$state" = "DISCONNECTED" ]; then
103+ stop
104+ exit 0
105+ fi
106+
107+ rm -f ~/.cache/upstart/mtp-server.log
108+end script
109+
110+exec /usr/bin/mtp-server &
111
112=== renamed file 'debian/mtp-examples.install' => 'debian/mtp-server.install'
113--- debian/mtp-examples.install 2013-06-13 10:22:21 +0000
114+++ debian/mtp-server.install 2013-09-11 16:32:38 +0000
115@@ -1,1 +1,2 @@
116-usr/bin/mtp-server
117\ No newline at end of file
118+usr/bin/mtp-server
119+debian/mtp-server.conf /usr/share/upstart/sessions/
120
121=== added file 'debian/mtp-server.mtp-server-bootup.upstart'
122--- debian/mtp-server.mtp-server-bootup.upstart 1970-01-01 00:00:00 +0000
123+++ debian/mtp-server.mtp-server-bootup.upstart 2013-09-11 16:32:38 +0000
124@@ -0,0 +1,27 @@
125+description "MTP protocol server bootup"
126+
127+start on android
128+
129+task
130+
131+emits android_usb-device-changed
132+
133+script
134+ if [ -x /usr/bin/setprop ]; then
135+ timeout=10
136+ # loop 10 times and then exit, if the property service
137+ # isnt up after 80 sec # it is likely not starting at all
138+ while [ ! -e /dev/socket/property_service ]; do
139+ sleep 8
140+ if [ "$timeout" -le 0 ]; then
141+ stop
142+ exit 0
143+ fi
144+ timeout=$(($timeout - 1))
145+ done
146+
147+ /usr/bin/setprop sys.usb.config mtp,adb
148+ fi
149+
150+ initctl emit android_usb-device-changed
151+end script
152
153=== modified file 'debian/rules'
154--- debian/rules 2013-06-13 10:22:21 +0000
155+++ debian/rules 2013-09-11 16:32:38 +0000
156@@ -1,13 +1,11 @@
157 #!/usr/bin/make -f
158-# -*- makefile -*-
159-# Sample debian/rules that uses debhelper.
160-# This file was originally written by Joey Hess and Craig Small.
161-# As a special exception, when this file is copied by dh-make into a
162-# dh-make output file, you may use that output file without restriction.
163-# This special exception was added by Craig Small in version 0.37 of dh-make.
164
165 # Uncomment this to turn on verbose mode.
166 # export DH_VERBOSE=1
167
168 %:
169- dh $@
170\ No newline at end of file
171+ dh $@
172+
173+override_dh_installinit:
174+ dh_installinit -pmtp-server --name=mtp-server-bootup
175+ dh_installinit
176
177=== renamed directory 'examples' => 'server'
178=== modified file 'server/CMakeLists.txt'
179--- examples/CMakeLists.txt 2013-06-13 10:22:21 +0000
180+++ server/CMakeLists.txt 2013-09-11 16:32:38 +0000
181@@ -5,13 +5,18 @@
182 server.cpp
183 )
184
185+set_target_properties(mtp-server PROPERTIES COMPILE_FLAGS -fPIC)
186+
187 target_link_libraries(
188 mtp-server
189 mtp
190 usbhost
191+ ${Boost_LIBRARIES}
192+ ${Boost_system_LIBRARIES}
193+ ${Boost_filesystem_LIBRARIES}
194 )
195
196 install(
197 TARGETS mtp-server
198 RUNTIME DESTINATION bin
199-)
200\ No newline at end of file
201+)
202
203=== renamed file 'examples/StubMtpDatabase.h' => 'server/UbuntuMtpDatabase.h'
204--- examples/StubMtpDatabase.h 2013-06-13 10:22:21 +0000
205+++ server/UbuntuMtpDatabase.h 2013-09-11 16:32:38 +0000
206@@ -1,3 +1,19 @@
207+/*
208+ * Copyright (C) 2013 Canonical Ltd.
209+ *
210+ * Licensed under the Apache License, Version 2.0 (the "License");
211+ * you may not use this file except in compliance with the License.
212+ * You may obtain a copy of the License at
213+ *
214+ * http://www.apache.org/licenses/LICENSE-2.0
215+ *
216+ * Unless required by applicable law or agreed to in writing, software
217+ * distributed under the License is distributed on an "AS IS" BASIS,
218+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
219+ * See the License for the specific language governing permissions and
220+ * limitations under the License.
221+ */
222+
223 #ifndef STUB_MTP_DATABASE_H_
224 #define STUB_MTP_DATABASE_H_
225
226@@ -7,73 +23,106 @@
227 #include <MtpObjectInfo.h>
228 #include <MtpProperty.h>
229
230+#include <cstdlib>
231 #include <cstring>
232 #include <iostream>
233 #include <map>
234+#include <vector>
235 #include <string>
236 #include <tuple>
237
238+#include <boost/foreach.hpp>
239+#include <boost/filesystem.hpp>
240+#include <boost/range/adaptors.hpp>
241+#include <boost/range/algorithm.hpp>
242+
243+using namespace boost::filesystem;
244+
245 namespace android
246 {
247-class StubMtpDatabase : public android::MtpDatabase {
248+class UbuntuMtpDatabase : public android::MtpDatabase {
249 private:
250 struct DbEntry
251 {
252 MtpStorageID storage_id;
253 std::string object_name;
254 MtpObjectFormat object_format;
255+ MtpObjectHandle parent;
256 size_t object_size;
257- size_t width;
258- size_t height;
259- size_t bit_depth;
260 std::string display_name;
261 std::string path;
262 };
263
264- enum PngImageHandles
265- {
266- png_image_1,
267- png_image_2,
268- png_image_3,
269- png_image_4,
270- png_image_5,
271- png_image_6,
272- png_image_7,
273- png_image_8,
274- png_image_9,
275- png_image_10,
276- png_image_size
277- };
278- static const uint32_t reserved_slots = png_image_size;
279-
280 uint32_t counter;
281- std::map<std::tuple<MtpStorageID, MtpObjectFormat>, MtpObjectHandleList> db =
282+ std::map<MtpObjectHandle, DbEntry> db;
283+
284+ void parse_directory(path p, MtpObjectHandle parent)
285 {
286+ DbEntry entry;
287+ std::vector<path> v;
288+
289+ copy(directory_iterator(p), directory_iterator(), std::back_inserter(v));
290+
291+ for (std::vector<path>::const_iterator it(v.begin()), it_end(v.end()); it != it_end; ++it)
292 {
293- std::make_tuple(MTP_STORAGE_REMOVABLE_RAM, MTP_FORMAT_PNG),
294- {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}
295+ MtpObjectHandle handle = counter;
296+
297+ counter++;
298+
299+ std::cout << " " << *it << " handle: " << handle << " parent: " << parent << std::endl;
300+
301+ entry.storage_id = MTP_STORAGE_FIXED_RAM;
302+ entry.parent = parent;
303+ entry.object_name = it->filename().string();
304+ entry.display_name = it->filename().string();
305+ entry.path = it->string();
306+
307+ if (is_regular_file (*it)) {
308+ entry.object_format = MTP_FORMAT_DEFINED;
309+ entry.object_size = file_size(*it);
310+
311+ db.insert( std::pair<MtpObjectHandle, DbEntry>(handle, entry) );
312+ } else if (is_directory (*it)) {
313+ entry.object_format = MTP_FORMAT_ASSOCIATION;
314+ entry.object_size = 0;
315+
316+ db.insert( std::pair<MtpObjectHandle, DbEntry>(handle, entry) );
317+
318+ parse_directory (*it, handle);
319+ }
320 }
321- };
322-
323- std::map<MtpObjectHandle, DbEntry> entries =
324+ }
325+
326+ void readFiles(const std::string& sourcedir)
327 {
328- {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"}},
329- {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"}},
330- {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"}},
331- {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"}},
332- {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"}},
333- {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"}},
334- {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"}},
335- {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"}},
336- {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"}},
337- {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"}}
338- };
339-
340+ path p (sourcedir);
341+
342+ try {
343+ if (exists(p)) {
344+ if (is_directory(p)) {
345+ std::cout << p << " is a directory containing:\n";
346+
347+ parse_directory (p, MTP_PARENT_ROOT);
348+ }
349+ } else
350+ std::cout << p << " does not exist\n";
351+ }
352+ catch (const filesystem_error& ex) {
353+ std::cout << ex.what() << '\n';
354+ }
355+
356+ }
357+
358 public:
359- StubMtpDatabase() : counter(StubMtpDatabase::reserved_slots)
360+ UbuntuMtpDatabase(const char *dir) : counter(1)
361 {
362+ db = std::map<MtpObjectHandle, DbEntry>();
363+ readFiles(std::string(dir));
364+
365+ std::cout << __PRETTY_FUNCTION__ << ": object count:" << db.size() << std::endl;
366 }
367- virtual ~StubMtpDatabase() {}
368+
369+ virtual ~UbuntuMtpDatabase() {}
370
371 // called from SendObjectInfo to reserve a database entry for the incoming file
372 virtual MtpObjectHandle beginSendObject(
373@@ -84,8 +133,25 @@
374 uint64_t size,
375 time_t modified)
376 {
377- std::cout << __PRETTY_FUNCTION__ << ": " << path << std::endl;
378- return counter++;
379+ DbEntry entry;
380+ MtpObjectHandle handle = counter;
381+ MtpObjectHandle parent_id = parent == 0 ? MTP_PARENT_ROOT : parent;
382+
383+ std::cout << __PRETTY_FUNCTION__ << ": " << path << " - " << parent << std::endl;
384+
385+ entry.storage_id = storage;
386+ entry.parent = parent_id;
387+ entry.object_name = std::string(basename(path.c_str()));
388+ entry.display_name = std::string(basename(path.c_str()));
389+ entry.path = path;
390+ entry.object_format = format;
391+ entry.object_size = size;
392+
393+ db.insert( std::pair<MtpObjectHandle, DbEntry>(handle, entry) );
394+
395+ counter++;
396+
397+ return handle;
398 }
399
400 // called to report success or failure of the SendObject file transfer
401@@ -98,6 +164,10 @@
402 bool succeeded)
403 {
404 std::cout << __PRETTY_FUNCTION__ << ": " << path << std::endl;
405+
406+ if (!succeeded) {
407+ db.erase(handle);
408+ }
409 }
410
411 virtual MtpObjectHandleList* getObjectList(
412@@ -109,7 +179,14 @@
413 MtpObjectHandleList* list = nullptr;
414 try
415 {
416- list = new MtpObjectHandleList(db.at(std::make_tuple(storageID, MTP_FORMAT_PNG)));
417+ std::vector<MtpObjectHandle> keys;
418+
419+ BOOST_FOREACH(MtpObjectHandle i, db | boost::adaptors::map_keys) {
420+ if (db.at(i).parent == parent)
421+ keys.push_back(i);
422+ }
423+
424+ list = new MtpObjectHandleList(keys);
425 } catch(...)
426 {
427 list = new MtpObjectHandleList();
428@@ -126,7 +203,7 @@
429 std::cout << __PRETTY_FUNCTION__ << ": " << storageID << ", " << format << ", " << parent << std::endl;
430 try
431 {
432- return db.at(std::make_tuple(storageID, MTP_FORMAT_PNG)).size();
433+ return db.size();
434 } catch(...)
435 {
436 }
437@@ -153,12 +230,15 @@
438 virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format)
439 {
440 std::cout << __PRETTY_FUNCTION__ << std::endl;
441+ /*
442 if (format != MTP_FORMAT_PNG)
443 return nullptr;
444+ */
445
446 static const MtpObjectPropertyList list =
447 {
448 MTP_PROPERTY_STORAGE_ID,
449+ MTP_PROPERTY_PARENT_OBJECT,
450 MTP_PROPERTY_OBJECT_FORMAT,
451 MTP_PROPERTY_OBJECT_SIZE,
452 MTP_PROPERTY_WIDTH,
453@@ -185,13 +265,11 @@
454 std::cout << __PRETTY_FUNCTION__ << std::endl;
455 switch(property)
456 {
457- case MTP_PROPERTY_STORAGE_ID: packet.putUInt32(entries.at(handle).storage_id); break;
458- case MTP_PROPERTY_OBJECT_FORMAT: packet.putUInt32(entries.at(handle).object_format); break;
459- case MTP_PROPERTY_OBJECT_SIZE: packet.putUInt32(entries.at(handle).object_size); break;
460- case MTP_PROPERTY_WIDTH: packet.putUInt32(entries.at(handle).width); break;
461- case MTP_PROPERTY_HEIGHT: packet.putUInt32(entries.at(handle).height); break;
462- case MTP_PROPERTY_IMAGE_BIT_DEPTH: packet.putUInt32(entries.at(handle).bit_depth); break;
463- case MTP_PROPERTY_DISPLAY_NAME: packet.putString(entries.at(handle).display_name.c_str()); break;
464+ case MTP_PROPERTY_STORAGE_ID: packet.putUInt32(db.at(handle).storage_id); break;
465+ case MTP_PROPERTY_PARENT_OBJECT: packet.putUInt32(db.at(handle).parent); break;
466+ case MTP_PROPERTY_OBJECT_FORMAT: packet.putUInt32(db.at(handle).object_format); break;
467+ case MTP_PROPERTY_OBJECT_SIZE: packet.putUInt32(db.at(handle).object_size); break;
468+ case MTP_PROPERTY_DISPLAY_NAME: packet.putString(db.at(handle).display_name.c_str()); break;
469 default: return MTP_RESPONSE_GENERAL_ERROR; break;
470 }
471
472@@ -248,22 +326,22 @@
473 {
474 std::cout << __PRETTY_FUNCTION__ << std::endl;
475 info.mHandle = handle;
476- info.mStorageID = entries.at(handle).storage_id;
477- info.mFormat = entries.at(handle).object_format;
478+ info.mStorageID = db.at(handle).storage_id;
479+ info.mFormat = db.at(handle).object_format;
480 info.mProtectionStatus = 0x0;
481 info.mCompressedSize = 0;
482- info.mThumbFormat = entries.at(handle).object_format;
483+ info.mThumbFormat = db.at(handle).object_format;
484 info.mThumbCompressedSize = 20*20*4;
485 info.mThumbPixWidth = 20;
486 info.mThumbPixHeight =20;
487 info.mImagePixWidth = 20;
488 info.mImagePixHeight = 20;
489 info.mImagePixDepth = 4;
490- info.mParent = MTP_PARENT_ROOT;
491+ info.mParent = db.at(handle).parent;
492 info.mAssociationType = 0;
493 info.mAssociationDesc = 0;
494 info.mSequenceNumber = 0;
495- info.mName = ::strdup("test");
496+ info.mName = ::strdup(db.at(handle).object_name.c_str());
497 info.mDateCreated = 0;
498 info.mDateModified = 0;
499 info.mKeywords = ::strdup("ubuntu,touch");
500@@ -273,10 +351,11 @@
501
502 virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize)
503 {
504- std::cout << __PRETTY_FUNCTION__ << std::endl;
505- outThumbSize = 20*20*4;
506- void* result = malloc(20*20*4);
507- memset(result, 0, 20*20*4);
508+ void* result;
509+
510+ outThumbSize = 0;
511+ memset(result, 0, outThumbSize);
512+
513 return result;
514 }
515
516@@ -286,17 +365,61 @@
517 int64_t& outFileLength,
518 MtpObjectFormat& outFormat)
519 {
520+ DbEntry entry = db.at(handle);
521+
522 std::cout << __PRETTY_FUNCTION__ << std::endl;
523- outFilePath = entries.at(handle).path;
524- outFileLength = 1024;
525- outFormat = entries.at(handle).object_format;
526+
527+ outFilePath = std::string(entry.path);
528+ outFileLength = entry.object_size;
529+ outFormat = entry.object_format;
530+
531+ return MTP_RESPONSE_OK;
532 }
533
534 virtual MtpResponseCode deleteFile(MtpObjectHandle handle)
535 {
536- std::cout << __PRETTY_FUNCTION__ << std::endl;
537- return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
538- }
539+ size_t orig_size = db.size();
540+ size_t new_size;
541+
542+ std::cout << __PRETTY_FUNCTION__ << std::endl;
543+
544+ new_size = db.erase(handle);
545+
546+ if (orig_size > new_size) {
547+ /* Recursively remove children object from the DB as well.
548+ * we can safely ignore failures here, since the objects
549+ * would not be reachable anyway.
550+ */
551+ BOOST_FOREACH(MtpObjectHandle i, db | boost::adaptors::map_keys) {
552+ if (db.at(i).parent == handle)
553+ db.erase(i);
554+ }
555+ return MTP_RESPONSE_OK;
556+ }
557+ else
558+ return MTP_RESPONSE_GENERAL_ERROR;
559+ }
560+
561+ /*
562+ virtual MtpResponseCode moveFile(MtpObjectHandle handle, MtpObjectHandle new_parent)
563+ {
564+ std::cout << __PRETTY_FUNCTION__ << std::endl;
565+
566+ // change parent
567+
568+ return MTP_RESPONSE_OK
569+ }
570+
571+ virtual MtpResponseCode copyFile(MtpObjectHandle handle, MtpObjectHandle new_parent)
572+ {
573+ std::cout << __PRETTY_FUNCTION__ << std::endl;
574+
575+ // duplicate DbEntry
576+ // change parent
577+
578+ return MTP_RESPONSE_OK
579+ }
580+ */
581
582 virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle)
583 {
584
585=== modified file 'server/server.cpp'
586--- examples/server.cpp 2013-06-13 10:22:21 +0000
587+++ server/server.cpp 2013-09-11 16:32:38 +0000
588@@ -1,4 +1,20 @@
589-#include "StubMtpDatabase.h"
590+/*
591+ * Copyright (C) 2013 Canonical Ltd.
592+ *
593+ * Licensed under the Apache License, Version 2.0 (the "License");
594+ * you may not use this file except in compliance with the License.
595+ * You may obtain a copy of the License at
596+ *
597+ * http://www.apache.org/licenses/LICENSE-2.0
598+ *
599+ * Unless required by applicable law or agreed to in writing, software
600+ * distributed under the License is distributed on an "AS IS" BASIS,
601+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
602+ * See the License for the specific language governing permissions and
603+ * limitations under the License.
604+ */
605+
606+#include "UbuntuMtpDatabase.h"
607
608 #include <MtpServer.h>
609 #include <MtpStorage.h>
610@@ -10,27 +26,23 @@
611 #include <sys/stat.h>
612 #include <fcntl.h>
613 #include <unistd.h>
614+#include <pwd.h>
615
616 namespace
617 {
618 struct FileSystemConfig
619 {
620- static const int file_group = 1023; // Taken from android's config. Might need to be adjusted.
621 static const int file_perm = 0664;
622 static const int directory_perm = 0755;
623 };
624
625-android::MtpStorage* removable_storage = new android::MtpStorage(
626- MTP_STORAGE_REMOVABLE_RAM,
627- ".",
628- "Dummy storage",
629- 1024 * 1024 * 1024 * 200,
630- true,
631- 1024 * 1024 * 1024);
632+android::MtpStorage* home_storage;
633+
634 }
635
636 int main(int argc, char** argv)
637 {
638+ struct passwd *userdata = getpwuid (getuid());
639 int fd = open("/dev/mtp_usb", O_RDWR);
640
641 if (fd < 0)
642@@ -38,17 +50,25 @@
643 std::cout << "Error opening /dev/mtp_usb, aborting now..." << std::endl;
644 }
645
646+ home_storage = new android::MtpStorage(
647+ MTP_STORAGE_FIXED_RAM,
648+ userdata->pw_dir,
649+ userdata->pw_name,
650+ 1024 * 1024 * 100, /* 100 MB reserved space, to avoid filling the disk */
651+ false,
652+ 1024 * 1024 * 1024 * 2 /* 2GB arbitrary max file size */);
653+
654 std::shared_ptr<android::MtpServer> server
655 {
656 new android::MtpServer(
657 fd,
658- new android::StubMtpDatabase(),
659+ new android::UbuntuMtpDatabase(userdata->pw_dir),
660 false,
661- FileSystemConfig::file_group,
662+ userdata->pw_gid,
663 FileSystemConfig::file_perm,
664 FileSystemConfig::directory_perm)
665 };
666- server->addStorage(removable_storage);
667+ server->addStorage(home_storage);
668 server->run();
669
670 /*
671
672=== modified file 'src/MtpUtils.cpp'
673--- src/MtpUtils.cpp 2013-06-13 10:22:21 +0000
674+++ src/MtpUtils.cpp 2013-09-11 16:32:38 +0000
675@@ -49,6 +49,7 @@
676
677 // hack to compute timezone
678 time_t dummy;
679+ tzset();
680 localtime_r(&dummy, &tm);
681
682 tm.tm_sec = second;
683
684=== added directory 'tests'
685=== added file 'tests/CMakeLists.txt'
686--- tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
687+++ tests/CMakeLists.txt 2013-09-11 16:32:38 +0000
688@@ -0,0 +1,91 @@
689+
690+# MtpUtils
691+add_executable(
692+ test-utils
693+ TestMtpUtils.cpp
694+)
695+
696+target_link_libraries(
697+ test-utils
698+ mtp
699+ usbhost
700+ ${Boost_LIBRARIES}
701+ ${Boost_unit_test_framework_LIBRARIES}
702+)
703+add_test(test-utils test-utils)
704+
705+# MtpDebug
706+add_executable(
707+ test-debug
708+ TestMtpDebug.cpp
709+)
710+
711+target_link_libraries(
712+ test-debug
713+ mtp
714+ usbhost
715+ ${Boost_LIBRARIES}
716+ ${Boost_unit_test_framework_LIBRARIES}
717+)
718+add_test(test-debug test-debug)
719+
720+# MtpPacket
721+add_executable(
722+ test-packet
723+ TestMtpPacket.cpp
724+)
725+
726+target_link_libraries(
727+ test-packet
728+ mtp
729+ usbhost
730+ ${Boost_LIBRARIES}
731+ ${Boost_unit_test_framework_LIBRARIES}
732+)
733+add_test(test-packet test-packet)
734+
735+# MtpProperty
736+add_executable(
737+ test-property
738+ TestMtpProperty.cpp
739+)
740+
741+target_link_libraries(
742+ test-property
743+ mtp
744+ usbhost
745+ ${Boost_LIBRARIES}
746+ ${Boost_unit_test_framework_LIBRARIES}
747+)
748+add_test(test-property test-property)
749+
750+# MtpStorage
751+add_executable(
752+ test-storage
753+ TestMtpStorage.cpp
754+)
755+
756+target_link_libraries(
757+ test-storage
758+ mtp
759+ usbhost
760+ ${Boost_LIBRARIES}
761+ ${Boost_unit_test_framework_LIBRARIES}
762+)
763+add_test(test-storage test-storage)
764+
765+# MtpServer
766+add_executable(
767+ test-server
768+ TestMtpServer.cpp
769+)
770+
771+target_link_libraries(
772+ test-server
773+ mtp
774+ usbhost
775+ ${Boost_LIBRARIES}
776+ ${Boost_unit_test_framework_LIBRARIES}
777+)
778+add_test(test-server test-server)
779+
780
781=== added file 'tests/MockMtpDatabase.h'
782--- tests/MockMtpDatabase.h 1970-01-01 00:00:00 +0000
783+++ tests/MockMtpDatabase.h 2013-09-11 16:32:38 +0000
784@@ -0,0 +1,358 @@
785+/*
786+ * Copyright (C) 2013 Canonical Ltd.
787+ *
788+ * Licensed under the Apache License, Version 2.0 (the "License");
789+ * you may not use this file except in compliance with the License.
790+ * You may obtain a copy of the License at
791+ *
792+ * http://www.apache.org/licenses/LICENSE-2.0
793+ *
794+ * Unless required by applicable law or agreed to in writing, software
795+ * distributed under the License is distributed on an "AS IS" BASIS,
796+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
797+ * See the License for the specific language governing permissions and
798+ * limitations under the License.
799+ */
800+
801+#ifndef STUB_MOCK_MTP_DATABASE_H_
802+#define STUB_MOCK_MTP_DATABASE_H_
803+
804+#include <mtp.h>
805+#include <MtpDatabase.h>
806+#include <MtpDataPacket.h>
807+#include <MtpObjectInfo.h>
808+#include <MtpProperty.h>
809+
810+#include <cstdlib>
811+#include <cstring>
812+#include <iostream>
813+#include <map>
814+#include <vector>
815+#include <string>
816+#include <tuple>
817+
818+#include <boost/foreach.hpp>
819+#include <boost/filesystem.hpp>
820+#include <boost/range/adaptors.hpp>
821+#include <boost/range/algorithm.hpp>
822+
823+namespace android
824+{
825+class MockMtpDatabase : public android::MtpDatabase {
826+private:
827+ struct DbEntry
828+ {
829+ MtpStorageID storage_id;
830+ std::string object_name;
831+ MtpObjectFormat object_format;
832+ MtpObjectHandle parent;
833+ size_t object_size;
834+ std::string display_name;
835+ std::string path;
836+ };
837+
838+ uint32_t counter;
839+ std::map<MtpObjectHandle, DbEntry> db;
840+
841+public:
842+ MockMtpDatabase() : counter(1)
843+ {
844+ DbEntry entry;
845+ db = std::map<MtpObjectHandle, DbEntry>();
846+
847+ entry.storage_id = 666;
848+ entry.object_name = std::string("Test Object");
849+ entry.object_format = MTP_FORMAT_PNG;
850+ entry.parent = MTP_PARENT_ROOT;
851+ entry.object_size = 666;
852+ entry.display_name = std::string("Test Object");
853+ entry.path = std::string("TestObject");
854+
855+ db.insert( std::pair<MtpObjectHandle, DbEntry>(counter, entry) );
856+ }
857+
858+ virtual ~MockMtpDatabase() {}
859+
860+ virtual MtpObjectHandle beginSendObject(
861+ const MtpString& path,
862+ MtpObjectFormat format,
863+ MtpObjectHandle parent,
864+ MtpStorageID storage,
865+ uint64_t size,
866+ time_t modified)
867+ {
868+ return 1;
869+ }
870+
871+ virtual void endSendObject(
872+ const MtpString& path,
873+ MtpObjectHandle handle,
874+ MtpObjectFormat format,
875+ bool succeeded)
876+ {
877+ std::cout << __PRETTY_FUNCTION__ << ": " << path << std::endl;
878+
879+ if (!succeeded) {
880+ db.erase(handle);
881+ }
882+ }
883+
884+ virtual MtpObjectHandleList* getObjectList(
885+ MtpStorageID storageID,
886+ MtpObjectFormat format,
887+ MtpObjectHandle parent)
888+ {
889+ MtpObjectHandleList* list = nullptr;
890+
891+ if (db.empty()) {
892+ list = new MtpObjectHandleList();
893+ } else {
894+ std::vector<MtpObjectHandle> keys;
895+ keys.push_back(1);
896+ list = new MtpObjectHandleList(keys);
897+ }
898+
899+ return list;
900+ }
901+
902+ virtual int getNumObjects(
903+ MtpStorageID storageID,
904+ MtpObjectFormat format,
905+ MtpObjectHandle parent)
906+ {
907+ return db.size();
908+ }
909+
910+ virtual MtpObjectFormatList* getSupportedPlaybackFormats()
911+ {
912+ std::cout << __PRETTY_FUNCTION__ << std::endl;
913+ static const MtpObjectFormatList list = {MTP_FORMAT_PNG};
914+ return new MtpObjectFormatList{list};
915+ }
916+
917+ virtual MtpObjectFormatList* getSupportedCaptureFormats()
918+ {
919+ std::cout << __PRETTY_FUNCTION__ << std::endl;
920+ static const MtpObjectFormatList list = {MTP_FORMAT_ASSOCIATION, MTP_FORMAT_PNG};
921+ return new MtpObjectFormatList{list};
922+ }
923+
924+ virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format)
925+ {
926+ std::cout << __PRETTY_FUNCTION__ << std::endl;
927+
928+ static const MtpObjectPropertyList list =
929+ {
930+ MTP_PROPERTY_STORAGE_ID,
931+ MTP_PROPERTY_PARENT_OBJECT,
932+ MTP_PROPERTY_OBJECT_FORMAT,
933+ MTP_PROPERTY_OBJECT_SIZE,
934+ MTP_PROPERTY_WIDTH,
935+ MTP_PROPERTY_HEIGHT,
936+ MTP_PROPERTY_IMAGE_BIT_DEPTH,
937+ MTP_PROPERTY_DISPLAY_NAME
938+ };
939+
940+ return new MtpObjectPropertyList{list};
941+ }
942+
943+ virtual MtpDevicePropertyList* getSupportedDeviceProperties()
944+ {
945+ std::cout << __PRETTY_FUNCTION__ << std::endl;
946+ static const MtpDevicePropertyList list = { MTP_DEVICE_PROPERTY_UNDEFINED };
947+ return new MtpDevicePropertyList{list};
948+ }
949+
950+ virtual MtpResponseCode getObjectPropertyValue(
951+ MtpObjectHandle handle,
952+ MtpObjectProperty property,
953+ MtpDataPacket& packet)
954+ {
955+ std::cout << __PRETTY_FUNCTION__ << std::endl;
956+ switch(property)
957+ {
958+ case MTP_PROPERTY_STORAGE_ID: packet.putUInt32(db.at(handle).storage_id); break;
959+ case MTP_PROPERTY_PARENT_OBJECT: packet.putUInt32(db.at(handle).parent); break;
960+ case MTP_PROPERTY_OBJECT_FORMAT: packet.putUInt32(db.at(handle).object_format); break;
961+ case MTP_PROPERTY_OBJECT_SIZE: packet.putUInt32(db.at(handle).object_size); break;
962+ case MTP_PROPERTY_DISPLAY_NAME: packet.putString(db.at(handle).display_name.c_str()); break;
963+ default: return MTP_RESPONSE_GENERAL_ERROR; break;
964+ }
965+
966+ return MTP_RESPONSE_OK;
967+ }
968+
969+ virtual MtpResponseCode setObjectPropertyValue(
970+ MtpObjectHandle handle,
971+ MtpObjectProperty property,
972+ MtpDataPacket& packet)
973+ {
974+ std::cout << __PRETTY_FUNCTION__ << std::endl;
975+ return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
976+ }
977+
978+ virtual MtpResponseCode getDevicePropertyValue(
979+ MtpDeviceProperty property,
980+ MtpDataPacket& packet)
981+ {
982+ std::cout << __PRETTY_FUNCTION__ << std::endl;
983+ return MTP_RESPONSE_GENERAL_ERROR;
984+ }
985+
986+ virtual MtpResponseCode setDevicePropertyValue(
987+ MtpDeviceProperty property,
988+ MtpDataPacket& packet)
989+ {
990+ std::cout << __PRETTY_FUNCTION__ << std::endl;
991+ return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
992+ }
993+
994+ virtual MtpResponseCode resetDeviceProperty(
995+ MtpDeviceProperty property)
996+ {
997+ std::cout << __PRETTY_FUNCTION__ << std::endl;
998+ return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
999+ }
1000+
1001+ virtual MtpResponseCode getObjectPropertyList(
1002+ MtpObjectHandle handle,
1003+ uint32_t format,
1004+ uint32_t property,
1005+ int groupCode,
1006+ int depth,
1007+ MtpDataPacket& packet)
1008+ {
1009+ std::cout << __PRETTY_FUNCTION__ << std::endl;
1010+ return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
1011+ }
1012+
1013+ virtual MtpResponseCode getObjectInfo(
1014+ MtpObjectHandle handle,
1015+ MtpObjectInfo& info)
1016+ {
1017+ std::cout << __PRETTY_FUNCTION__ << std::endl;
1018+ info.mHandle = handle;
1019+ info.mStorageID = db.at(handle).storage_id;
1020+ info.mFormat = db.at(handle).object_format;
1021+ info.mProtectionStatus = 0x0;
1022+ info.mCompressedSize = 0;
1023+ info.mThumbFormat = db.at(handle).object_format;
1024+ info.mThumbCompressedSize = 20*20*4;
1025+ info.mThumbPixWidth = 20;
1026+ info.mThumbPixHeight =20;
1027+ info.mImagePixWidth = 20;
1028+ info.mImagePixHeight = 20;
1029+ info.mImagePixDepth = 4;
1030+ info.mParent = db.at(handle).parent;
1031+ info.mAssociationType = 0;
1032+ info.mAssociationDesc = 0;
1033+ info.mSequenceNumber = 0;
1034+ info.mName = ::strdup(db.at(handle).object_name.c_str());
1035+ info.mDateCreated = 0;
1036+ info.mDateModified = 0;
1037+ info.mKeywords = ::strdup("test");
1038+
1039+ return MTP_RESPONSE_OK;
1040+ }
1041+
1042+ virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize)
1043+ {
1044+ void* result;
1045+
1046+ outThumbSize = 0;
1047+ memset(result, 0, outThumbSize);
1048+
1049+ return result;
1050+ }
1051+
1052+ virtual MtpResponseCode getObjectFilePath(
1053+ MtpObjectHandle handle,
1054+ MtpString& outFilePath,
1055+ int64_t& outFileLength,
1056+ MtpObjectFormat& outFormat)
1057+ {
1058+ DbEntry entry = db.at(handle);
1059+
1060+ std::cout << __PRETTY_FUNCTION__ << std::endl;
1061+
1062+ outFilePath = std::string(entry.path);
1063+ outFileLength = entry.object_size;
1064+ outFormat = entry.object_format;
1065+
1066+ return MTP_RESPONSE_OK;
1067+ }
1068+
1069+ virtual MtpResponseCode deleteFile(MtpObjectHandle handle)
1070+ {
1071+ size_t orig_size = db.size();
1072+ size_t new_size;
1073+
1074+ std::cout << __PRETTY_FUNCTION__ << std::endl;
1075+
1076+ new_size = db.erase(handle);
1077+
1078+ if (orig_size > new_size) {
1079+ BOOST_FOREACH(MtpObjectHandle i, db | boost::adaptors::map_keys) {
1080+ if (db.at(i).parent == handle)
1081+ db.erase(i);
1082+ }
1083+ return MTP_RESPONSE_OK;
1084+ }
1085+ else
1086+ return MTP_RESPONSE_GENERAL_ERROR;
1087+ }
1088+
1089+ virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle)
1090+ {
1091+ std::cout << __PRETTY_FUNCTION__ << std::endl;
1092+ return nullptr;
1093+ }
1094+
1095+ virtual MtpResponseCode setObjectReferences(
1096+ MtpObjectHandle handle,
1097+ MtpObjectHandleList* references)
1098+ {
1099+ std::cout << __PRETTY_FUNCTION__ << std::endl;
1100+ return MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
1101+ }
1102+
1103+ virtual MtpProperty* getObjectPropertyDesc(
1104+ MtpObjectProperty property,
1105+ MtpObjectFormat format)
1106+ {
1107+ std::cout << __PRETTY_FUNCTION__ << std::endl;
1108+ MtpProperty* result = nullptr;
1109+ switch(property)
1110+ {
1111+ case MTP_PROPERTY_STORAGE_ID: result = new MtpProperty(property, MTP_TYPE_UINT32); break;
1112+ case MTP_PROPERTY_OBJECT_FORMAT: result = new MtpProperty(property, MTP_TYPE_UINT32); break;
1113+ case MTP_PROPERTY_OBJECT_SIZE: result = new MtpProperty(property, MTP_TYPE_UINT32); break;
1114+ case MTP_PROPERTY_WIDTH: result = new MtpProperty(property, MTP_TYPE_UINT32); break;
1115+ case MTP_PROPERTY_HEIGHT: result = new MtpProperty(property, MTP_TYPE_UINT32); break;
1116+ case MTP_PROPERTY_IMAGE_BIT_DEPTH: result = new MtpProperty(property, MTP_TYPE_UINT32); break;
1117+ case MTP_PROPERTY_DISPLAY_NAME: result = new MtpProperty(property, MTP_TYPE_STR); break;
1118+ default: break;
1119+ }
1120+
1121+ return result;
1122+ }
1123+
1124+ virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property)
1125+ {
1126+ std::cout << __PRETTY_FUNCTION__ << std::endl;
1127+ return new MtpProperty(MTP_DEVICE_PROPERTY_UNDEFINED, MTP_TYPE_UNDEFINED);
1128+ }
1129+
1130+ virtual void sessionStarted()
1131+ {
1132+ std::cout << __PRETTY_FUNCTION__ << std::endl;
1133+ }
1134+
1135+ virtual void sessionEnded()
1136+ {
1137+ std::cout << __PRETTY_FUNCTION__ << std::endl;
1138+ }
1139+};
1140+}
1141+
1142+#endif // STUB_MOCK_MTP_DATABASE_H_
1143
1144=== added file 'tests/TestMtpDebug.cpp'
1145--- tests/TestMtpDebug.cpp 1970-01-01 00:00:00 +0000
1146+++ tests/TestMtpDebug.cpp 2013-09-11 16:32:38 +0000
1147@@ -0,0 +1,49 @@
1148+/*
1149+ * Copyright (C) 2013 Canonical Ltd.
1150+ *
1151+ * Licensed under the Apache License, Version 2.0 (the "License");
1152+ * you may not use this file except in compliance with the License.
1153+ * You may obtain a copy of the License at
1154+ *
1155+ * http://www.apache.org/licenses/LICENSE-2.0
1156+ *
1157+ * Unless required by applicable law or agreed to in writing, software
1158+ * distributed under the License is distributed on an "AS IS" BASIS,
1159+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1160+ * See the License for the specific language governing permissions and
1161+ * limitations under the License.
1162+ */
1163+
1164+#define BOOST_TEST_DYN_LINK
1165+#define BOOST_TEST_MAIN
1166+#include <boost/test/unit_test.hpp>
1167+
1168+#include "mtp.h"
1169+#include "MtpDebug.h"
1170+
1171+using namespace android;
1172+
1173+BOOST_AUTO_TEST_CASE(DebugGetOperationCodeName)
1174+{
1175+ BOOST_CHECK_EQUAL( MtpDebug::getOperationCodeName(MTP_OPERATION_GET_DEVICE_INFO), "MTP_OPERATION_GET_DEVICE_INFO" );
1176+}
1177+
1178+BOOST_AUTO_TEST_CASE(DebugGetFormatCodeName)
1179+{
1180+ BOOST_CHECK_EQUAL( MtpDebug::getFormatCodeName(MTP_FORMAT_PNG), "MTP_FORMAT_PNG" );
1181+}
1182+
1183+BOOST_AUTO_TEST_CASE(DebugGetObjectPropCodeName)
1184+{
1185+ BOOST_CHECK_EQUAL( MtpDebug::getObjectPropCodeName(MTP_PROPERTY_STORAGE_ID), "MTP_PROPERTY_STORAGE_ID" );
1186+}
1187+
1188+BOOST_AUTO_TEST_CASE(DebugGetDevicePropCodeName)
1189+{
1190+ BOOST_CHECK_EQUAL( MtpDebug::getDevicePropCodeName(MTP_DEVICE_PROPERTY_BATTERY_LEVEL), "MTP_DEVICE_PROPERTY_BATTERY_LEVEL" );
1191+}
1192+
1193+BOOST_AUTO_TEST_CASE(DebugGetCodeNameUnknown)
1194+{
1195+ BOOST_CHECK_EQUAL( MtpDebug::getOperationCodeName (1), "UNKNOWN");
1196+}
1197
1198=== added file 'tests/TestMtpPacket.cpp'
1199--- tests/TestMtpPacket.cpp 1970-01-01 00:00:00 +0000
1200+++ tests/TestMtpPacket.cpp 2013-09-11 16:32:38 +0000
1201@@ -0,0 +1,50 @@
1202+/*
1203+ * Copyright (C) 2013 Canonical Ltd.
1204+ *
1205+ * Licensed under the Apache License, Version 2.0 (the "License");
1206+ * you may not use this file except in compliance with the License.
1207+ * You may obtain a copy of the License at
1208+ *
1209+ * http://www.apache.org/licenses/LICENSE-2.0
1210+ *
1211+ * Unless required by applicable law or agreed to in writing, software
1212+ * distributed under the License is distributed on an "AS IS" BASIS,
1213+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1214+ * See the License for the specific language governing permissions and
1215+ * limitations under the License.
1216+ */
1217+
1218+#define BOOST_TEST_DYN_LINK
1219+#define BOOST_TEST_MAIN
1220+#include <boost/test/unit_test.hpp>
1221+
1222+#include "mtp.h"
1223+#include "MtpPacket.h"
1224+
1225+using namespace android;
1226+
1227+BOOST_AUTO_TEST_CASE(Packet)
1228+{
1229+ MtpPacket *p = new MtpPacket (4);
1230+
1231+ BOOST_REQUIRE(p);
1232+}
1233+
1234+BOOST_AUTO_TEST_CASE(PacketReset)
1235+{
1236+ MtpPacket *p = new MtpPacket (MTP_CONTAINER_PARAMETER_OFFSET + 4);
1237+ uint32_t value = UINT32_MAX;
1238+ uint32_t result;
1239+
1240+ BOOST_REQUIRE(p);
1241+
1242+ p->setParameter(1, value);
1243+ result = p->getParameter(1);
1244+ BOOST_CHECK_EQUAL (value, result);
1245+
1246+ p->reset();
1247+
1248+ result = p->getParameter(1);
1249+ BOOST_CHECK (value != result);
1250+ BOOST_CHECK (result == 0);
1251+}
1252
1253=== added file 'tests/TestMtpProperty.cpp'
1254--- tests/TestMtpProperty.cpp 1970-01-01 00:00:00 +0000
1255+++ tests/TestMtpProperty.cpp 2013-09-11 16:32:38 +0000
1256@@ -0,0 +1,95 @@
1257+/*
1258+ * Copyright (C) 2013 Canonical Ltd.
1259+ *
1260+ * Licensed under the Apache License, Version 2.0 (the "License");
1261+ * you may not use this file except in compliance with the License.
1262+ * You may obtain a copy of the License at
1263+ *
1264+ * http://www.apache.org/licenses/LICENSE-2.0
1265+ *
1266+ * Unless required by applicable law or agreed to in writing, software
1267+ * distributed under the License is distributed on an "AS IS" BASIS,
1268+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1269+ * See the License for the specific language governing permissions and
1270+ * limitations under the License.
1271+ */
1272+
1273+#define BOOST_TEST_DYN_LINK
1274+#define BOOST_TEST_MAIN
1275+#include <boost/test/unit_test.hpp>
1276+
1277+#include "mtp.h"
1278+#include "MtpProperty.h"
1279+#include "MtpStringBuffer.h"
1280+
1281+using namespace android;
1282+
1283+BOOST_AUTO_TEST_CASE(PropertyConstructorString)
1284+{
1285+ MtpProperty *prop = new MtpProperty(MTP_PROPERTY_NAME, MTP_TYPE_STR, false);
1286+
1287+ BOOST_CHECK (prop);
1288+ BOOST_CHECK (prop->mType == MTP_TYPE_STR);
1289+ BOOST_CHECK (prop->mCode == MTP_PROPERTY_NAME);
1290+ BOOST_CHECK (prop->mWriteable == false);
1291+
1292+ BOOST_CHECK (prop->mDefaultValue.u.u64 == 0);
1293+ BOOST_CHECK (prop->mCurrentValue.u.u64 == 0);
1294+}
1295+
1296+BOOST_AUTO_TEST_CASE(PropertyConstructorUInt32)
1297+{
1298+ MtpProperty *prop = new MtpProperty(MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32, true, 42);
1299+
1300+ BOOST_CHECK (prop);
1301+ BOOST_CHECK (prop->mType == MTP_TYPE_UINT32);
1302+ BOOST_CHECK (prop->mCode == MTP_PROPERTY_STORAGE_ID);
1303+ BOOST_CHECK (prop->mWriteable == true);
1304+
1305+ BOOST_CHECK (prop->mDefaultValue.u.u32 == 42);
1306+ BOOST_CHECK (prop->mCurrentValue.u.u64 == 0);
1307+}
1308+
1309+BOOST_AUTO_TEST_CASE(PropertySetFormRange)
1310+{
1311+ MtpProperty *prop = new MtpProperty(MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32, true, 42);
1312+
1313+ prop->setFormRange(0, 90, 2);
1314+
1315+ BOOST_CHECK(prop->mMinimumValue.u.u32 == 0);
1316+ BOOST_CHECK(prop->mMaximumValue.u.u32 == 90);
1317+ BOOST_CHECK(prop->mStepSize.u.u32 == 2);
1318+}
1319+
1320+BOOST_AUTO_TEST_CASE(PropertySetFormEnum)
1321+{
1322+ MtpProperty *prop = new MtpProperty(MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32, true, 42);
1323+ const int values[4] = { 1, 2, 3, 4, };
1324+
1325+ prop->setFormEnum(values, 4);
1326+
1327+ BOOST_CHECK(prop->mEnumValues[0].u.u32 == 1);
1328+ BOOST_CHECK(prop->mEnumValues[1].u.u32 == 2);
1329+ BOOST_CHECK(prop->mEnumValues[2].u.u32 == 3);
1330+ BOOST_CHECK(prop->mEnumValues[3].u.u32 == 4);
1331+}
1332+
1333+BOOST_AUTO_TEST_CASE(PropertySetFormDateTime)
1334+{
1335+ MtpProperty *prop = new MtpProperty(MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32, true, 42);
1336+
1337+ prop->setFormDateTime();
1338+
1339+ BOOST_CHECK(prop->mFormFlag == MtpProperty::kFormDateTime);
1340+}
1341+
1342+BOOST_AUTO_TEST_CASE(PropertyPrintToBuffer)
1343+{
1344+ MtpProperty *prop = new MtpProperty(MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32, true, 42);
1345+ std::string expected ("42");
1346+ std::string result;
1347+
1348+ prop->print(prop->mDefaultValue, result);
1349+
1350+ BOOST_CHECK (result == expected);
1351+}
1352
1353=== added file 'tests/TestMtpServer.cpp'
1354--- tests/TestMtpServer.cpp 1970-01-01 00:00:00 +0000
1355+++ tests/TestMtpServer.cpp 2013-09-11 16:32:38 +0000
1356@@ -0,0 +1,72 @@
1357+/*
1358+ * Copyright (C) 2013 Canonical Ltd.
1359+ *
1360+ * Licensed under the Apache License, Version 2.0 (the "License");
1361+ * you may not use this file except in compliance with the License.
1362+ * You may obtain a copy of the License at
1363+ *
1364+ * http://www.apache.org/licenses/LICENSE-2.0
1365+ *
1366+ * Unless required by applicable law or agreed to in writing, software
1367+ * distributed under the License is distributed on an "AS IS" BASIS,
1368+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1369+ * See the License for the specific language governing permissions and
1370+ * limitations under the License.
1371+ */
1372+
1373+#define BOOST_TEST_DYN_LINK
1374+#define BOOST_TEST_MAIN
1375+#include <boost/test/unit_test.hpp>
1376+
1377+#include "mtp.h"
1378+#include "MockMtpDatabase.h"
1379+#include "MtpServer.h"
1380+#include "MtpStorage.h"
1381+
1382+using namespace android;
1383+
1384+BOOST_AUTO_TEST_CASE(ServerConstructor)
1385+{
1386+ MtpDatabase *db = new MockMtpDatabase ();
1387+ MtpServer *server = new MtpServer (0, db, false, 0, 0, 0);
1388+
1389+ BOOST_CHECK(server);
1390+}
1391+
1392+BOOST_AUTO_TEST_CASE(ServerAddGetStorage)
1393+{
1394+ MtpDatabase *db = new MockMtpDatabase ();
1395+ MtpServer *server = new MtpServer (0, db, false, 0, 0, 0);
1396+ MtpStorage *storage = new MtpStorage (666, "/tmp", "Test storage", 0, false, 64);
1397+
1398+ server->addStorage(storage);
1399+
1400+ BOOST_CHECK(server->getStorage(666) != NULL);
1401+}
1402+
1403+BOOST_AUTO_TEST_CASE(ServerGetStorageNull)
1404+{
1405+ MtpDatabase *db = new MockMtpDatabase ();
1406+ MtpServer *server = new MtpServer (0, db, false, 0, 0, 0);
1407+
1408+ BOOST_CHECK(server->getStorage(666) == NULL);
1409+}
1410+
1411+BOOST_AUTO_TEST_CASE(ServerHasStorageTrue)
1412+{
1413+ MtpDatabase *db = new MockMtpDatabase ();
1414+ MtpServer *server = new MtpServer (0, db, false, 0, 0, 0);
1415+ MtpStorage *storage = new MtpStorage (666, "/tmp", "Test storage", 0, false, 64);
1416+
1417+ server->addStorage(storage);
1418+
1419+ BOOST_CHECK(server->hasStorage(666));
1420+}
1421+
1422+BOOST_AUTO_TEST_CASE(ServerHasStorageFalse)
1423+{
1424+ MtpDatabase *db = new MockMtpDatabase ();
1425+ MtpServer *server = new MtpServer (0, db, false, 0, 0, 0);
1426+
1427+ BOOST_CHECK(server->hasStorage(667) == false);
1428+}
1429
1430=== added file 'tests/TestMtpStorage.cpp'
1431--- tests/TestMtpStorage.cpp 1970-01-01 00:00:00 +0000
1432+++ tests/TestMtpStorage.cpp 2013-09-11 16:32:38 +0000
1433@@ -0,0 +1,87 @@
1434+/*
1435+ * Copyright (C) 2013 Canonical Ltd.
1436+ *
1437+ * Licensed under the Apache License, Version 2.0 (the "License");
1438+ * you may not use this file except in compliance with the License.
1439+ * You may obtain a copy of the License at
1440+ *
1441+ * http://www.apache.org/licenses/LICENSE-2.0
1442+ *
1443+ * Unless required by applicable law or agreed to in writing, software
1444+ * distributed under the License is distributed on an "AS IS" BASIS,
1445+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1446+ * See the License for the specific language governing permissions and
1447+ * limitations under the License.
1448+ */
1449+
1450+#define BOOST_TEST_DYN_LINK
1451+#define BOOST_TEST_MAIN
1452+#include <boost/test/unit_test.hpp>
1453+
1454+#include "mtp.h"
1455+#include "MtpStorage.h"
1456+
1457+using namespace android;
1458+
1459+BOOST_AUTO_TEST_CASE(StorageConstructor)
1460+{
1461+ MtpStorage *s = new MtpStorage (666, "/tmp", "Test storage", 0, false, 64);
1462+
1463+ BOOST_CHECK(s);
1464+}
1465+
1466+BOOST_AUTO_TEST_CASE(StorageGetTypeFixed)
1467+{
1468+ MtpStorage *s = new MtpStorage (666, "/tmp", "Test storage", 0, false, 64);
1469+
1470+ BOOST_CHECK (s->getType() == MTP_STORAGE_FIXED_RAM);
1471+}
1472+
1473+BOOST_AUTO_TEST_CASE(StorageGetTypeRemovable)
1474+{
1475+ MtpStorage *s = new MtpStorage (666, "/tmp", "Test storage", 0, true, 64);
1476+
1477+ BOOST_CHECK (s->getType() == MTP_STORAGE_REMOVABLE_RAM);
1478+}
1479+
1480+BOOST_AUTO_TEST_CASE(StorageGetFileSystemType)
1481+{
1482+ MtpStorage *s = new MtpStorage (666, "/tmp", "Test storage", 0, true, 64);
1483+
1484+ BOOST_CHECK (s->getFileSystemType() == MTP_STORAGE_FILESYSTEM_HIERARCHICAL);
1485+}
1486+
1487+BOOST_AUTO_TEST_CASE(StorageGetAccessCapa)
1488+{
1489+ MtpStorage *s = new MtpStorage (666, "/tmp", "Test storage", 0, true, 64);
1490+
1491+ BOOST_CHECK (s->getAccessCapability() == MTP_STORAGE_READ_WRITE);
1492+}
1493+
1494+BOOST_AUTO_TEST_CASE(StorageGetMaxCapacity)
1495+{
1496+ MtpStorage *s = new MtpStorage (666, "/tmp", "Test storage", 0, true, 64);
1497+
1498+ BOOST_CHECK (s->getMaxCapacity() > 0);
1499+}
1500+
1501+BOOST_AUTO_TEST_CASE(StorageGetMaxCapacityInvalidPath)
1502+{
1503+ MtpStorage *s = new MtpStorage (666, "", "Test storage", 0, true, 64);
1504+
1505+ BOOST_CHECK (s->getMaxCapacity() == -1);
1506+}
1507+
1508+BOOST_AUTO_TEST_CASE(StoageGetFreeSpace)
1509+{
1510+ MtpStorage *s = new MtpStorage (666, "/", "Test storage", 0, true, 64);
1511+
1512+ BOOST_CHECK (s->getFreeSpace() != -1);
1513+}
1514+
1515+BOOST_AUTO_TEST_CASE(StorageGetDescription)
1516+{
1517+ MtpStorage *s = new MtpStorage (666, "/", "Test storage", 0, true, 64);
1518+
1519+ BOOST_CHECK_EQUAL( strcmp( s->getDescription(), "Test storage" ), 0);
1520+}
1521
1522=== added file 'tests/TestMtpUtils.cpp'
1523--- tests/TestMtpUtils.cpp 1970-01-01 00:00:00 +0000
1524+++ tests/TestMtpUtils.cpp 2013-09-11 16:32:38 +0000
1525@@ -0,0 +1,48 @@
1526+/*
1527+ * Copyright (C) 2013 Canonical Ltd.
1528+ *
1529+ * Licensed under the Apache License, Version 2.0 (the "License");
1530+ * you may not use this file except in compliance with the License.
1531+ * You may obtain a copy of the License at
1532+ *
1533+ * http://www.apache.org/licenses/LICENSE-2.0
1534+ *
1535+ * Unless required by applicable law or agreed to in writing, software
1536+ * distributed under the License is distributed on an "AS IS" BASIS,
1537+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1538+ * See the License for the specific language governing permissions and
1539+ * limitations under the License.
1540+ */
1541+
1542+#define BOOST_TEST_DYN_LINK
1543+#define BOOST_TEST_MAIN
1544+#include <boost/test/unit_test.hpp>
1545+
1546+#include <cstdlib>
1547+
1548+// #include <cutils/tztime.h>
1549+#include "MtpUtils.h"
1550+
1551+using namespace android;
1552+
1553+BOOST_AUTO_TEST_CASE(UtilsParseDateTime)
1554+{
1555+ time_t seconds;
1556+
1557+ setenv("TZ", "UTC", 1);
1558+
1559+ parseDateTime("20130909T114143", seconds);
1560+ BOOST_CHECK_EQUAL(seconds, 1378726903l);
1561+}
1562+
1563+BOOST_AUTO_TEST_CASE(UtilsFormatDateTime)
1564+{
1565+ time_t seconds = 1378726903;
1566+ char buffer[25];
1567+ char *expected = "20130909T114143";
1568+
1569+ setenv("TZ", "UTC", 1);
1570+
1571+ formatDateTime(seconds, buffer, 25);
1572+ BOOST_CHECK_EQUAL(strcmp(expected, buffer), 0);
1573+}

Subscribers

People subscribed via source and target branches