1/*
2 * Copyright (C) 2017 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 androidx.room.integration.kotlintestapp.test
18
19import android.database.sqlite.SQLiteConstraintException
20import android.support.test.filters.SdkSuppress
21import android.support.test.filters.SmallTest
22import androidx.arch.core.executor.ArchTaskExecutor
23import androidx.room.integration.kotlintestapp.vo.Author
24import androidx.room.integration.kotlintestapp.vo.Book
25import androidx.room.integration.kotlintestapp.vo.BookWithPublisher
26import androidx.room.integration.kotlintestapp.vo.Lang
27import androidx.room.integration.kotlintestapp.vo.Publisher
28import com.google.common.base.Optional
29import io.reactivex.Flowable
30import io.reactivex.schedulers.Schedulers
31import io.reactivex.subscribers.TestSubscriber
32import org.hamcrest.CoreMatchers
33import org.hamcrest.CoreMatchers.`is`
34import org.hamcrest.CoreMatchers.equalTo
35import org.hamcrest.CoreMatchers.instanceOf
36import org.hamcrest.CoreMatchers.notNullValue
37import org.hamcrest.MatcherAssert.assertThat
38import org.junit.Assert.assertNotNull
39import org.junit.Test
40import java.util.Date
41
42@SmallTest
43class BooksDaoTest : TestDatabaseTest() {
44
45    @Test
46    fun bookById() {
47        booksDao.addAuthors(TestUtil.AUTHOR_1)
48        booksDao.addPublishers(TestUtil.PUBLISHER)
49        booksDao.addBooks(TestUtil.BOOK_1)
50
51        assertThat(booksDao.getBook(TestUtil.BOOK_1.bookId), `is`<Book>(TestUtil.BOOK_1))
52    }
53
54    @SdkSuppress(minSdkVersion = 24)
55    @Test
56    fun bookByIdJavaOptional() {
57        booksDao.addAuthors(TestUtil.AUTHOR_1)
58        booksDao.addPublishers(TestUtil.PUBLISHER)
59        booksDao.addBooks(TestUtil.BOOK_1)
60
61        assertThat(
62                booksDao.getBookJavaOptional(TestUtil.BOOK_1.bookId),
63                `is`<java.util.Optional<Book>>(java.util.Optional.of(TestUtil.BOOK_1)))
64    }
65
66    @SdkSuppress(minSdkVersion = 24)
67    @Test
68    fun bookByIdJavaOptionalEmpty() {
69        assertThat(
70                booksDao.getBookJavaOptional(TestUtil.BOOK_1.bookId),
71                `is`<java.util.Optional<Book>>(java.util.Optional.empty()))
72    }
73
74    @Test
75    fun bookByIdListenableFuture() {
76        booksDao.addAuthors(TestUtil.AUTHOR_1)
77        booksDao.addPublishers(TestUtil.PUBLISHER)
78        booksDao.addBooks(TestUtil.BOOK_1)
79
80        assertThat(
81                booksDao.getBookListenableFuture(TestUtil.BOOK_1.bookId).get(),
82                `is`<Book>(TestUtil.BOOK_1))
83    }
84
85    @Test
86    fun bookByIdOptional() {
87        booksDao.addAuthors(TestUtil.AUTHOR_1)
88        booksDao.addPublishers(TestUtil.PUBLISHER)
89        booksDao.addBooks(TestUtil.BOOK_1)
90
91        assertThat(
92                booksDao.getBookOptional(TestUtil.BOOK_1.bookId),
93                `is`<Optional<Book>>(Optional.of(TestUtil.BOOK_1)))
94    }
95
96    @Test
97    fun bookByIdOptionalListenableFuture() {
98        booksDao.addAuthors(TestUtil.AUTHOR_1)
99        booksDao.addPublishers(TestUtil.PUBLISHER)
100        booksDao.addBooks(TestUtil.BOOK_1)
101
102        assertThat(
103                booksDao.getBookOptionalListenableFuture(TestUtil.BOOK_1.bookId).get(),
104                `is`<Optional<Book>>(Optional.of(TestUtil.BOOK_1)))
105    }
106
107    @Test
108    fun bookByIdOptionalListenableFutureAbsent() {
109        assertThat(
110                booksDao.getBookOptionalListenableFuture(TestUtil.BOOK_1.bookId).get(),
111                `is`<Optional<Book>>(Optional.absent()))
112    }
113
114    @Test
115    fun bookByIdOptionalAbsent() {
116        assertThat(
117                booksDao.getBookOptional(TestUtil.BOOK_1.bookId),
118                `is`<Optional<Book>>(Optional.absent()))
119    }
120
121    @Test
122    fun bookByIdOptionalFlowable() {
123        booksDao.addAuthors(TestUtil.AUTHOR_1)
124        booksDao.addPublishers(TestUtil.PUBLISHER)
125        booksDao.addBooks(TestUtil.BOOK_1)
126
127        val subscriber = TestSubscriber<Optional<Book>>()
128        val flowable: Flowable<Optional<Book>> =
129                booksDao.getBookOptionalFlowable(TestUtil.BOOK_1.bookId)
130        flowable.observeOn(Schedulers.from(ArchTaskExecutor.getMainThreadExecutor()))
131                .subscribeWith(subscriber)
132
133        assertThat(subscriber.values().size, `is`(1))
134        assertThat(subscriber.values()[0], `is`(Optional.of(TestUtil.BOOK_1)))
135    }
136
137    @Test
138    fun bookByIdOptionalFlowableAbsent() {
139        val subscriber = TestSubscriber<Optional<Book>>()
140        val flowable: Flowable<Optional<Book>> =
141                booksDao.getBookOptionalFlowable(TestUtil.BOOK_1.bookId)
142        flowable.observeOn(Schedulers.from(ArchTaskExecutor.getMainThreadExecutor()))
143                .subscribeWith(subscriber)
144
145        assertThat(subscriber.values().size, `is`(1))
146        assertThat(subscriber.values()[0], `is`(Optional.absent()))
147    }
148
149    @Test
150    fun bookWithPublisher() {
151        booksDao.addAuthors(TestUtil.AUTHOR_1)
152        booksDao.addPublishers(TestUtil.PUBLISHER)
153        booksDao.addBooks(TestUtil.BOOK_1)
154
155        val expected = BookWithPublisher(TestUtil.BOOK_1.bookId, TestUtil.BOOK_1.title,
156                TestUtil.PUBLISHER)
157        val expectedList = ArrayList<BookWithPublisher>()
158        expectedList.add(expected)
159
160        assertThat(database.booksDao().getBooksWithPublisher(),
161                `is`<List<BookWithPublisher>>(expectedList))
162    }
163
164    @Test
165    fun bookWithPublisherListenableFuture() {
166        booksDao.addAuthors(TestUtil.AUTHOR_1)
167        booksDao.addPublishers(TestUtil.PUBLISHER)
168        booksDao.addBooks(TestUtil.BOOK_1)
169
170        val expected = BookWithPublisher(TestUtil.BOOK_1.bookId, TestUtil.BOOK_1.title,
171                TestUtil.PUBLISHER)
172        val expectedList = ArrayList<BookWithPublisher>()
173        expectedList.add(expected)
174
175        assertThat(database.booksDao().getBooksWithPublisherListenableFuture().get(),
176                `is`<List<BookWithPublisher>>(expectedList))
177    }
178
179    @Test
180    fun updateBookWithNullTitle() {
181        booksDao.addPublishers(TestUtil.PUBLISHER)
182        booksDao.addBooks(TestUtil.BOOK_1)
183
184        var throwable: Throwable? = null
185        try {
186            booksDao.updateBookTitle(TestUtil.BOOK_1.bookId, null)
187        } catch (t: Throwable) {
188            throwable = t
189        }
190        assertNotNull(throwable)
191        assertThat<Throwable>(throwable, instanceOf<Throwable>(SQLiteConstraintException::class
192                .java))
193    }
194
195    @Test
196    fun publisherWithBooks() {
197        booksDao.addAuthors(TestUtil.AUTHOR_1)
198        booksDao.addPublishers(TestUtil.PUBLISHER)
199        booksDao.addBooks(TestUtil.BOOK_1, TestUtil.BOOK_2)
200
201        val actualPublisherWithBooks = booksDao.getPublisherWithBooks(
202                TestUtil.PUBLISHER.publisherId)
203
204        assertThat(actualPublisherWithBooks.publisher, `is`<Publisher>(TestUtil.PUBLISHER))
205        assertThat(actualPublisherWithBooks.books?.size, `is`(2))
206        assertThat(actualPublisherWithBooks.books?.get(0), `is`<Book>(TestUtil.BOOK_1))
207        assertThat(actualPublisherWithBooks.books?.get(1), `is`<Book>(TestUtil.BOOK_2))
208    }
209
210    @Test // b/68077506
211    fun publisherWithBookSales() {
212        booksDao.addAuthors(TestUtil.AUTHOR_1)
213        booksDao.addPublishers(TestUtil.PUBLISHER)
214        booksDao.addBooks(TestUtil.BOOK_1, TestUtil.BOOK_2)
215        val actualPublisherWithBooks = booksDao.getPublisherWithBookSales(
216                TestUtil.PUBLISHER.publisherId)
217
218        assertThat(actualPublisherWithBooks.publisher, `is`<Publisher>(TestUtil.PUBLISHER))
219        assertThat(actualPublisherWithBooks.sales, `is`(listOf(TestUtil.BOOK_1.salesCnt,
220                TestUtil.BOOK_2.salesCnt)))
221    }
222
223    @Test
224    fun insertAuthorWithAllFields() {
225        val author = Author("id", "name", Date(), ArrayList())
226        database.booksDao().addAuthors(author)
227
228        val authorDb = database.booksDao().getAuthor(author.authorId)
229
230        assertThat(authorDb, CoreMatchers.`is`<Author>(author))
231    }
232
233    @Test
234    fun insertInInheritedDao() {
235        database.derivedDao().insert(TestUtil.AUTHOR_1)
236
237        val author = database.derivedDao().getAuthor(TestUtil.AUTHOR_1.authorId)
238
239        assertThat(author, CoreMatchers.`is`<Author>(TestUtil.AUTHOR_1))
240    }
241
242    @Test
243    fun findBooksInMultiLineQuery() {
244        booksDao.addPublishers(TestUtil.PUBLISHER)
245        booksDao.addBooks(TestUtil.BOOK_1)
246        booksDao.addBooks(TestUtil.BOOK_2)
247
248        val books = database.booksDao().getBooksMultiLineQuery(arrayListOf(
249                TestUtil.BOOK_1.bookId,
250                TestUtil.BOOK_2.bookId))
251        assertThat(books, `is`(listOf(TestUtil.BOOK_2, TestUtil.BOOK_1)))
252    }
253
254    @Test
255    fun findBooksByLanguage() {
256        booksDao.addPublishers(TestUtil.PUBLISHER)
257        val book1 = TestUtil.BOOK_1.copy(languages = setOf(Lang.TR))
258        val book2 = TestUtil.BOOK_2.copy(languages = setOf(Lang.ES, Lang.TR))
259        val book3 = TestUtil.BOOK_3.copy(languages = setOf(Lang.EN))
260        booksDao.addBooks(book1, book2, book3)
261
262        assertThat(booksDao.findByLanguages(setOf(Lang.EN, Lang.TR)),
263                `is`(listOf(book1, book2, book3)))
264
265        assertThat(booksDao.findByLanguages(setOf(Lang.TR)),
266                `is`(listOf(book1, book2)))
267
268        assertThat(booksDao.findByLanguages(setOf(Lang.ES)),
269                `is`(listOf(book2)))
270
271        assertThat(booksDao.findByLanguages(setOf(Lang.EN)),
272                `is`(listOf(book3)))
273    }
274
275    @Test
276    fun insertVarargInInheritedDao() {
277        database.derivedDao().insertAllArg(TestUtil.AUTHOR_1, TestUtil.AUTHOR_2)
278
279        val author = database.derivedDao().getAuthor(TestUtil.AUTHOR_1.authorId)
280
281        assertThat(author, CoreMatchers.`is`<Author>(TestUtil.AUTHOR_1))
282    }
283
284    @Test
285    fun insertListInInheritedDao() {
286        database.derivedDao().insertAll(listOf(TestUtil.AUTHOR_1))
287
288        val author = database.derivedDao().getAuthor(TestUtil.AUTHOR_1.authorId)
289
290        assertThat(author, CoreMatchers.`is`<Author>(TestUtil.AUTHOR_1))
291    }
292
293    @Test
294    fun deleteAndAddPublisher() {
295        booksDao.addPublishers(TestUtil.PUBLISHER)
296        booksDao.getPublishers().run {
297            assertThat(this.size, `is`(1))
298            assertThat(this.first(), `is`(equalTo(TestUtil.PUBLISHER)))
299        }
300        booksDao.deleteAndAddPublisher(TestUtil.PUBLISHER, TestUtil.PUBLISHER2)
301        booksDao.getPublishers().run {
302            assertThat(this.size, `is`(1))
303            assertThat(this.first(), `is`(equalTo(TestUtil.PUBLISHER2)))
304        }
305    }
306
307    @Test
308    fun deleteAndAddPublisher_failure() {
309        booksDao.addPublishers(TestUtil.PUBLISHER)
310        booksDao.getPublishers().run {
311            assertThat(this.size, `is`(1))
312            assertThat(this.first(), `is`(equalTo(TestUtil.PUBLISHER)))
313        }
314        var throwable: Throwable? = null
315        try {
316            booksDao.deleteAndAddPublisher(TestUtil.PUBLISHER, TestUtil.PUBLISHER2, true)
317        } catch (e: RuntimeException) {
318            throwable = e
319        }
320        assertThat(throwable, `is`(notNullValue()))
321        booksDao.getPublishers().run {
322            assertThat(this.size, `is`(1))
323            assertThat(this.first(), `is`(equalTo(TestUtil.PUBLISHER)))
324        }
325    }
326}
327