1/*
2 * Copyright (C) 2011 The Android Open Source Project
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
17package com.android.providers.contacts;
18
19import android.content.res.Resources;
20import android.test.AndroidTestCase;
21import android.test.suitebuilder.annotation.SmallTest;
22
23import com.google.android.collect.Maps;
24
25import java.io.ByteArrayOutputStream;
26import java.io.IOException;
27import java.io.InputStream;
28import java.util.Map;
29
30/**
31 * Adds support for loading photo files easily from test resources.
32 */
33@SmallTest
34public class PhotoLoadingTestCase extends AndroidTestCase {
35
36    private Map<Integer, PhotoEntry> photoResourceCache = Maps.newHashMap();
37    protected static enum PhotoSize {
38        ORIGINAL,
39        DISPLAY_PHOTO,
40        THUMBNAIL
41    }
42
43    protected final class PhotoEntry {
44        Map<PhotoSize, byte[]> photoMap = Maps.newHashMap();
45        public PhotoEntry(byte[] original) {
46            try {
47                PhotoProcessor processor = newPhotoProcessor(original, false);
48                photoMap.put(PhotoSize.ORIGINAL, original);
49                photoMap.put(PhotoSize.DISPLAY_PHOTO, processor.getDisplayPhotoBytes());
50                photoMap.put(PhotoSize.THUMBNAIL, processor.getThumbnailPhotoBytes());
51            } catch (IOException ignored) {
52                // Test is probably going to fail as a result anyway.
53            }
54        }
55
56        public byte[] getPhoto(PhotoSize size) {
57            return photoMap.get(size);
58        }
59    }
60
61    // The test photo will be loaded frequently in tests, so we'll just process it once.
62    private static PhotoEntry testPhotoEntry;
63
64    /**
65     * Create a new {@link PhotoProcessor} for unit tests.
66     *
67     * The instance generated here is always configured for 256x256 regardless of the
68     * device memory size.
69     */
70    protected PhotoProcessor newPhotoProcessor(byte[] data, boolean forceCropToSquare)
71            throws IOException {
72        return new PhotoProcessor(data, 256, 96, forceCropToSquare);
73    }
74
75    protected byte[] loadTestPhoto() {
76        int testPhotoId = com.android.providers.contacts.tests.R.drawable.ic_contact_picture;
77        if (testPhotoEntry == null) {
78            loadPhotoFromResource(testPhotoId, PhotoSize.ORIGINAL);
79            testPhotoEntry = photoResourceCache.get(testPhotoId);
80        }
81        return testPhotoEntry.getPhoto(PhotoSize.ORIGINAL);
82    }
83
84    protected byte[] loadTestPhoto(PhotoSize size) {
85        loadTestPhoto();
86        return testPhotoEntry.getPhoto(size);
87    }
88
89    protected byte[] loadPhotoFromResource(int resourceId, PhotoSize size) {
90        PhotoEntry entry = photoResourceCache.get(resourceId);
91        if (entry == null) {
92            final Resources resources = getTestContext().getResources();
93            InputStream is = resources.openRawResource(resourceId);
94            byte[] content = readInputStreamFully(is);
95            entry = new PhotoEntry(content);
96            photoResourceCache.put(resourceId, entry);
97        }
98        return entry.getPhoto(size);
99    }
100
101    protected byte[] readInputStreamFully(InputStream is) {
102        ByteArrayOutputStream os = new ByteArrayOutputStream();
103        byte[] buffer = new byte[10000];
104        int count;
105        try {
106            while ((count = is.read(buffer)) != -1) {
107                os.write(buffer, 0, count);
108            }
109            is.close();
110        } catch (IOException e) {
111            throw new RuntimeException(e);
112        }
113        return os.toByteArray();
114    }
115}
116