NodeInfo: replace Int by Long in upload limits, add test cases

main
Alibek Omarov 5 years ago
parent 25b57f3db4
commit 930e05be27
  1. 8
      app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeActivity.kt
  2. 8
      app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeViewModel.kt
  3. 2
      app/src/main/java/com/keylesspalace/tusky/components/compose/DownsizeImageTask.java
  4. 16
      app/src/main/java/com/keylesspalace/tusky/components/compose/MediaUploader.kt
  5. 14
      app/src/main/java/com/keylesspalace/tusky/entity/NodeInfo.kt
  6. 120
      app/src/test/java/com/keylesspalace/tusky/ComposeActivityTest.kt

@ -122,7 +122,8 @@ class ComposeActivity : BaseActivity(),
var maximumTootCharacters = DEFAULT_CHARACTER_LIMIT
private var composeOptions: ComposeOptions? = null
private val viewModel: ComposeViewModel by viewModels { viewModelFactory }
@VisibleForTesting
val viewModel: ComposeViewModel by viewModels { viewModelFactory }
private var suggestFormattingSyntax: String = "text/markdown"
private var mediaCount = 0
@ -346,8 +347,9 @@ class ComposeActivity : BaseActivity(),
enableButton(composeAddMediaButton, true, true)
enablePollButton(true)
}
private var supportedFormattingSyntax = arrayListOf<String>()
@VisibleForTesting
var supportedFormattingSyntax = arrayListOf<String>()
private fun subscribeToUpdates(mediaAdapter: MediaPreviewAdapter) {
withLifecycleContext {

@ -560,8 +560,8 @@ fun <T> mutableLiveData(default: T) = MutableLiveData<T>().apply { value = defau
const val DEFAULT_CHARACTER_LIMIT = 500
private const val DEFAULT_MAX_OPTION_COUNT = 4
private const val DEFAULT_MAX_OPTION_LENGTH = 25
private const val STATUS_VIDEO_SIZE_LIMIT = 41943040 // 40MiB
private const val STATUS_IMAGE_SIZE_LIMIT = 8388608 // 8MiB
private const val STATUS_VIDEO_SIZE_LIMIT : Long = 41943040 // 40MiB
private const val STATUS_IMAGE_SIZE_LIMIT : Long = 8388608 // 8MiB
data class ComposeInstanceParams(
@ -576,6 +576,6 @@ data class ComposeInstanceMetadata(
val supportsMarkdown: Boolean,
val supportsBBcode: Boolean,
val supportsHTML: Boolean,
val videoLimit: Int,
val imageLimit: Int
val videoLimit: Long,
val imageLimit: Long
)

@ -75,7 +75,7 @@ public class DownsizeImageTask extends AsyncTask<Uri, Void, Boolean> {
super.onPostExecute(successful);
}
public static boolean resize(Uri[] uris, int sizeLimit, ContentResolver contentResolver,
public static boolean resize(Uri[] uris, long sizeLimit, ContentResolver contentResolver,
File tempFile) {
for (Uri uri : uris) {
InputStream inputStream;

@ -59,8 +59,8 @@ fun createNewImageFile(context: Context): File {
data class PreparedMedia(val type: Int, val uri: Uri, val size: Long)
interface MediaUploader {
fun prepareMedia(inUri: Uri, videoLimit: Int, imageLimit: Int, filename: String?): Single<PreparedMedia>
fun uploadMedia(media: QueuedMedia, videoLimit: Int, imageLimit: Int): Observable<UploadEvent>
fun prepareMedia(inUri: Uri, videoLimit: Long, imageLimit: Long, filename: String?): Single<PreparedMedia>
fun uploadMedia(media: QueuedMedia, videoLimit: Long, imageLimit: Long): Observable<UploadEvent>
}
class AudioSizeException : Exception()
@ -73,14 +73,14 @@ class MediaUploaderImpl(
private val context: Context,
private val mastodonApi: MastodonApi
) : MediaUploader {
override fun uploadMedia(media: QueuedMedia, videoLimit: Int, imageLimit: Int): Observable<UploadEvent> {
override fun uploadMedia(media: QueuedMedia, videoLimit: Long, imageLimit: Long): Observable<UploadEvent> {
return Observable
.fromCallable {
if (shouldResizeMedia(media, imageLimit)) {
downsize(media, imageLimit)
} else media
}
.switchMap { upload(it, videoLimit, imageLimit) }
.switchMap { upload(it) }
.subscribeOn(Schedulers.io())
}
@ -94,7 +94,7 @@ class MediaUploaderImpl(
}
}
override fun prepareMedia(inUri: Uri, videoLimit: Int, imageLimit: Int, filename: String?): Single<PreparedMedia> {
override fun prepareMedia(inUri: Uri, videoLimit: Long, imageLimit: Long, filename: String?): Single<PreparedMedia> {
return Single.fromCallable {
var mediaSize = getMediaSize(contentResolver, inUri)
var uri = inUri
@ -159,7 +159,7 @@ class MediaUploaderImpl(
private val contentResolver = context.contentResolver
private fun upload(media: QueuedMedia, videoLimit: Int, imageLimit: Int): Observable<UploadEvent> {
private fun upload(media: QueuedMedia): Observable<UploadEvent> {
return Observable.create { emitter ->
var (mimeType, fileExtension) = getMimeTypeAndSuffixFromFilenameOrUri(media.uri, media.originalFileName)
val filename = String.format("%s_%s_%s%s",
@ -196,13 +196,13 @@ class MediaUploaderImpl(
}
}
private fun downsize(media: QueuedMedia, imageLimit: Int): QueuedMedia {
private fun downsize(media: QueuedMedia, imageLimit: Long): QueuedMedia {
val file = createNewImageFile(context)
DownsizeImageTask.resize(arrayOf(media.uri), imageLimit, context.contentResolver, file)
return media.copy(uri = file.toUri(), mediaSize = file.length())
}
private fun shouldResizeMedia(media: QueuedMedia, imageLimit: Int): Boolean {
private fun shouldResizeMedia(media: QueuedMedia, imageLimit: Long): Boolean {
// resize only images
if(media.type == QueuedMedia.Type.IMAGE) {
// resize when exceed image limit

@ -25,7 +25,7 @@ data class NodeInfoLink(
)
data class NodeInfoLinks(
val links: ArrayList<NodeInfoLink>
val links: List<NodeInfoLink>
)
// we care only about supported postFormats
@ -41,14 +41,14 @@ data class NodeInfoSoftware(
)
data class NodeInfoPleromaUploadLimits(
val avatar: Int?,
val background: Int?,
val banner: Int?,
val general: Int?
val avatar: Long?,
val background: Long?,
val banner: Long?,
val general: Long?
)
data class NodeInfoPixelfedUploadLimits(
@SerializedName("max_photo_size") val maxPhotoSize: Int?
@SerializedName("max_photo_size") val maxPhotoSize: Long?
)
data class NodeInfoPixelfedConfig(
@ -56,7 +56,7 @@ data class NodeInfoPixelfedConfig(
)
data class NodeInfoMetadata(
val postFormats: ArrayList<String>?,
val postFormats: List<String>?,
val uploadLimits: NodeInfoPleromaUploadLimits?,
val config: NodeInfoPixelfedConfig?
)

@ -41,6 +41,7 @@ import org.mockito.Mockito.mock
import org.robolectric.Robolectric
import org.robolectric.annotation.Config
import org.robolectric.fakes.RoboMenuItem
import java.lang.Math.pow
/**
* Created by charlag on 3/7/18.
@ -75,9 +76,7 @@ class ComposeActivityTest {
notificationLight = true
)
var instanceResponseCallback: (()->Instance)? = null
private val nodeinfoLinks = NodeInfoLinks(
links = arrayListOf<NodeInfoLink>()
)
var nodeinfoResponseCallback: (()->NodeInfo)? = null
@Before
fun setupActivity() {
@ -89,7 +88,27 @@ class ComposeActivityTest {
apiMock = mock(MastodonApi::class.java)
`when`(apiMock.getCustomEmojis()).thenReturn(Single.just(emptyList()))
`when`(apiMock.getNodeinfoLinks()).thenReturn(Single.just(nodeinfoLinks))
`when`(apiMock.getNodeinfoLinks()).thenReturn(object: Single<NodeInfoLinks>() {
override fun subscribeActual(observer: SingleObserver<in NodeInfoLinks>) {
if (nodeinfoResponseCallback == null) {
observer.onError(Throwable())
} else {
observer.onSuccess(NodeInfoLinks(
listOf( NodeInfoLink( "", "" ) )
))
}
}
})
`when`(apiMock.getNodeinfo("")).thenReturn(object: Single<NodeInfo>() {
override fun subscribeActual(observer: SingleObserver< in NodeInfo>) {
val nodeinfo = nodeinfoResponseCallback?.invoke()
if (nodeinfo == null) {
observer.onError(Throwable())
} else {
observer.onSuccess(nodeinfo)
}
}
})
`when`(apiMock.getInstance()).thenReturn(object: Single<Instance>() {
override fun subscribeActual(observer: SingleObserver<in Instance>) {
val instance = instanceResponseCallback?.invoke()
@ -164,12 +183,66 @@ class ComposeActivityTest {
@Test
fun whenMaximumTootCharsIsPopulated_customLimitIsUsed() {
val customMaximum = 1000
val customMaximum = 2147483647
instanceResponseCallback = { getInstanceWithMaximumTootCharacters(customMaximum) }
setupActivity()
assertEquals(customMaximum, activity.maximumTootCharacters)
}
@Test
fun whenPleromaInNodeinfo_attachmentLimitsRemoved() {
nodeinfoResponseCallback = { getPleromaNodeinfo(
null,
NodeInfoPleromaUploadLimits( 100, 100, 100, 100 ))
}
setupActivity()
assertEquals(true, activity.viewModel.hasNoAttachmentLimits)
}
@Test
fun whenPleromaInNodeinfo_haveFormatting() {
nodeinfoResponseCallback = { getPleromaNodeinfo(
listOf("text/plain", "text/markdown", "text/bbcode"),
NodeInfoPleromaUploadLimits( 100, 100, 100, 100 ))
}
setupActivity()
assertArrayEquals(arrayOf("text/markdown", "text/bbcode"), activity.supportedFormattingSyntax.toTypedArray())
}
@Test
fun whenPleromaInNodeinfo_haveCustomUploadLimits() {
nodeinfoResponseCallback = { getPleromaNodeinfo(
null,
NodeInfoPleromaUploadLimits( Long.MAX_VALUE, Long.MAX_VALUE, Long.MAX_VALUE, Long.MAX_VALUE ))
}
setupActivity()
assertEquals(Long.MAX_VALUE, activity.viewModel.instanceMetadata.value!!.imageLimit)
assertEquals(Long.MAX_VALUE, activity.viewModel.instanceMetadata.value!!.videoLimit)
}
@Test
fun whenPixelfedInNodeInfo_haveCustomUploadLimits() {
nodeinfoResponseCallback = { getPixelfedNodeinfo( 1024 * 1024 ) }
setupActivity()
assertEquals(1024 * 1024 * 1024, activity.viewModel.instanceMetadata.value!!.imageLimit)
assertEquals(1024 * 1024 * 1024, activity.viewModel.instanceMetadata.value!!.videoLimit)
assertArrayEquals(emptyArray(), activity.supportedFormattingSyntax.toTypedArray()) // pixelfed has no formatting
}
@Test
fun whenMastodonInNodeinfo_butItsAGlitch() {
nodeinfoResponseCallback = { getMastodonNodeinfo( "3.1.0+glitch" ) }
setupActivity()
assertArrayEquals(arrayOf("text/markdown", "text/html"), activity.supportedFormattingSyntax.toTypedArray())
}
@Test
fun whenMastodonInNodeinfo_butItsBoringVanilla() {
nodeinfoResponseCallback = { getMastodonNodeinfo( "3.1.0" ) }
setupActivity()
assertArrayEquals(emptyArray(), activity.supportedFormattingSyntax.toTypedArray())
}
@Test
fun whenTextContainsNoUrl_everyCharacterIsCounted() {
val content = "This is test content please ignore thx "
@ -361,6 +434,43 @@ class ComposeActivityTest {
activity.findViewById<EditText>(R.id.composeEditField).setText(text ?: "Some text")
}
private fun getPleromaNodeinfo(postFormats: List<String>?, limits: NodeInfoPleromaUploadLimits) : NodeInfo
{
return NodeInfo(
NodeInfoMetadata(
postFormats,
limits,
null
),
NodeInfoSoftware(
"pleroma",
"2.0.0"
)
)
}
private fun getPixelfedNodeinfo(maxPhotoSize: Long) : NodeInfo {
return NodeInfo(
NodeInfoMetadata(
null, null, NodeInfoPixelfedConfig( NodeInfoPixelfedUploadLimits( maxPhotoSize ) )
),
NodeInfoSoftware(
"pixelfed",
"2.0.0"
)
)
}
private fun getMastodonNodeinfo(version: String) : NodeInfo {
return NodeInfo(
null,
NodeInfoSoftware(
"mastodon",
version
)
)
}
private fun getInstanceWithMaximumTootCharacters(maximumTootCharacters: Int?): Instance
{
return Instance(

Loading…
Cancel
Save