Setting local variables inside a function for unit testing kotlin - kotlin

I'm trying to testing a function in android.For the function to be tested ,have to set local variable inside the function. Heres the code:
fun needToBeTested(serviceContext: Context):Int
{
val manager = serviceContext.getSystemService(Context.USB_SERVICE) as UsbManager
val deviceList = manager.deviceList
if(deviceList.size != 0){
val deviceIterator = deviceList.values.iterator()
while (deviceIterator.hasNext()) {
val device = deviceIterator.next()
if ((device != null)&&(device.deviceClass == 255)) { // USB_CLASS_VENDOR_SPEC - HUB
val permitToRead:Boolean = manager.hasPermission(device)
if(permitToRead){
setUpConnection(device,serviceContext)
} else{
manager.requestPermission(device, permissionIntent)
}
deviceConnectionStatus = 1
} else if((device != null) &&(device.deviceClass == 0)){ // USB_CLASS_PER_INTERFACE - USB STICK
}
}
} else (deviceList.size == 0){
connectionStatus = 0
}
}
Test class
class Test {
val mockContext = ApplicationProvider.getApplicationContext<Context>()
#Test
fun needTobeTested_returnOne(){
asserThat(sample.needToBeTested(mockContext)==1) //successcase
}
}
For testing this class,need to set the value of deviceList.Is there any way to set the value of 'x' from the test class for testing this function. Im new to android and testing.Any help would be really helpful.

Related

Kotlin, memory saving

I'm working on Splay Tree. I have a lot of command input (add, delete and etc), Hence the output is also huge (32MB of text in a txt file)
I have a memory problem, I am currently using two MultitableList and I have 200 MB of virtual memory (128 MB is needed for the project)
I run on Linux with the command:
$ kotlinc Kotlin.kt -include-runtime -d outPutFile.jar
$ /usr/bin/time -v java -jar outPutFile.jar
result: Maximum resident set size (kbytes): 249732 (With each launch different sizes but about 200)
how can i reduce the size? I need to change the size after each cycle
class SplayTree {
var ROOT: Node? = null
class Node(val key: Long, var value: String?) {
var _parent: SplayTree.Node? = null
var _RightChild: SplayTree.Node? = null
var _LeftChild: SplayTree.Node? = null
... there is a code here ...
// for output
override fun toString(): String {
if (_parent == null) {
return "[${key} ${value}]"
} else {
return "[${key} ${value} ${_parent!!.key}]"
}
}
}
... there is a code here ...
override fun toString(): String {
if (ROOT == null) {
return "_"
}
println(ROOT)
var NOWqueueList: List<Node?> = listOf(ROOT)
var BABYqueue: MutableList<Node?> = MutableList(0) { null }
//var NOWqueueList = Array<Node?>(1, {ROOT}) // Array
//var BABYqueue = Array<Node?>(1, {null}) // Array
//var n = 1 // Array
for (h in 1 until height(ROOT)) {
// for Array
//var pos = -1
//n *= 2
//BABYqueue = Array<Node?>(n, {null}) //for future line
for (ROOTList in NOWqueueList) {
//pos++ // Array
if ( ROOTList != null){
//left
if (ROOTList.haveLeftBaby()) {
//BABYqueue[pos] = ROOTList._LeftChild // Array
BABYqueue.add(ROOTList._LeftChild)
print(ROOTList._LeftChild.toString())
print(" ")
} else {
//BABYqueue[pos] = null // Array
BABYqueue.add(null)
print("_ ")
}
//pos++ // Array
//right
if (ROOTList.haveRightBaby()) {
//BABYqueue[pos] = ROOTList._RightChild // Array
BABYqueue.add(ROOTList._RightChild)
print(ROOTList._RightChild.toString())
print(" ")
} else {
//BABYqueue[pos] = null
BABYqueue.add(null)
print("_ ")
}
} else{ //если пустой то + 2 "_"
//BABYqueue[pos] = null // Array
//pos++ // Array
//BABYqueue[pos] = null // Array
BABYqueue.add(null)
BABYqueue.add(null)
print("_ _ ")
}
}
//NOWqueueList.clear() //worked when was MultitableList
NOWqueueList = BABYqueue.toList() // equate
//NOWqueueList = BABYqueue.clone() // Array
//println(NOWqueueList.joinToString(" ")) // вывожу готовый
println()
BABYqueue.clear()
}
//NOWqueueList.clear()
BABYqueue.clear()
return " end="
}
}
fun main() {
... there is a code here ...
}
I tried using Array, it still came out as with MultitableList

Cannot format given Object as a Number in Kotlin

An error occurred while using the ConverPrice function as follows for information about the price.
The price of the item in the recycler view adapter onBindViewHolder.
As a result of debugging, the error occurs in the following code.
priceText =
"${dec.format(priceMin)} ~ ${dec.format(priceMax)}"
Please check my code and answer.
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is DataViewHolder -> {
val item = dataList[position]
item.price.let {
holder.price.text = ConvertPrice(item, holder.price)
}
}
}
}
fun ConvertPrice(productDetail: ProductDetail?, tv: TextView? = null, setPrice: Boolean = false): String {
val disableColor = Color.parseColor("#aaaaaa")
val enableColor = Color.parseColor("#3692ff")
tv?.setTextColor(disableColor)
if (ProductDetail != null) {
val priceMin = productDetail.priceMin
val priceMax = productDetail.priceMax
var priceText = ""
val dec = DecimalFormat("##,###")
productDetail.enabledRetail?.let {
if (productDetail.enabledRetail == true) {
if (setPrice) {
priceText = if (priceMin == null || priceMax == null) {
"No pricing information"
} else {
"${dec.format(priceMin)} ~ ${dec.format(priceMax)}"
}
tv?.setTextColor(disableColor)
}
else {
priceText = dec.format(wineDetail.price).toString()
tv?.setTextColor(enableColor)
}
return priceText
} else if (productDetail.cntRating!! > 0) {
if ((priceMin == null && priceMax == null) || (priceMin == 0 && priceMax == 0)) {
priceText = "No pricing information"
} else {
priceText =
"${dec.format(priceMin)} ~ ${dec.format(priceMax)}"
tv?.setTextColor(disableColor)
}
return priceText
}
}
}
return "No pricing information"
}
DecimalFormat.format() only works fine with long or double. You should convert "priceMin" and "priceMax" to Long.
val priceMin = productDetail.priceMin.toLong()
val priceMax = productDetail.priceMax.toLong()
I recommend to use NumberFormat instead of DecimalFormat because it is locale-sensitive
val decFormat = NumberFormat.getInstance() // or getCurrencyInstance()
decFormat.maximumFractionDigits = 3
decFormat.format(priceMin)
decFormat.format(priceMax)

Conditional statement in getter method

Am relatively new to java so I have no idea what the problem is. In my getter settings of this class, I'm trying to evaluate if the input is of integer 1, 2 or 3, then it will return one of the previously saved setters described here. I used the same conditional statements in the setter, but the getter tells me that my method needs to return type int. What am I doing wrong? Or should I be doing this a completely different way? lol.
public class AssignmentMarks {
private String courseName;
private int assignment1 = 0, assignment2 = 0, assignment3 = 0;
public AssignmentMarks(String name, int mark1, int mark2, int mark3){
//create constructor to use variables.
this.courseName = name;
this.assignment1 = mark1;
this.assignment2 = mark2;
this.assignment3 = mark3;
}
public void setMark(int assignmentNumber, int mark) {
//assign value of the assignments
if(assignmentNumber == 1) {
mark = this.assignment1;
}else if(assignmentNumber == 2) {
mark = this.assignment2;
}else if(assignmentNumber == 3){
mark = this.assignment3;
}
}
public int getMark(int assignmentNum) {
if(assignmentNum == 1) {
return assignment1;
}else if (assignmentNum == 2) {
return assignment2;
} else if (assignmentNum == 3) {
return assignment3;
}
}
}
public int getMark(int assignmentNum) {
if(assignmentNum == 1) {
return assignment1;
}else if (assignmentNum == 2) {
return assignment2;
} else if (assignmentNum == 3) {
return assignment3;
}
// in another case
throw new Exception("Assignment must be 1, 2 or 3);
}
for setter
public void setMark(int assignmentNumber, int mark) {
//assign value of the assignments
if(assignmentNumber == 1) {
// BAD mark = this.assignment1; don't set parameter is useless
this.assignment1=mark;
}else if(assignmentNumber == 2) {
// BAD mark = this.assignment2;
this.assignment2=mark;
}else if(assignmentNumber == 3){
// BAD mark = this.assignment3;
this.assignment3=mark;
}
// in another case
throw new Exception("Assignment must be 1, 2 or 3");
}
I don't remember if you must import Exception for throwing them.
if yes put import java.lang.Exception on top of your code.
your logic can be improved using arrays, but let's walk, and after you will running...

How to move the snap position from center to left of RecycleView using SnapHelper?

I have an RecycleView that contains ImageViews and my question is how can i move the snap to be on the left side of the RecycleView instead of the center?
When i move the ImageViews they get snapped in the center and I can move them to the left or right inside that "snap window" by overriding the CalculateDistanceToFinalSnap method. I think I would now need to move that "snap window" to the left side of the RecycleView but I don't know how, or maybe there is another way, please help.
Here is a image of my problem, maybe it will help you to understand more clearly:
image
#Jessie Zhang -MSFT's solution works for me. The code was a little oddly formatted and I had some difficulty bringing it over. Here is the same solution (for a horizontal snap only) in Kotlin.
class StartSnapHelper: LinearSnapHelper() {
override fun calculateDistanceToFinalSnap(layoutManager: RecyclerView.LayoutManager, targetView: View): IntArray? {
return if (layoutManager.canScrollHorizontally()) {
val outer = mutableListOf<Int>()
outer.add(distanceToStart(targetView, getHorizontalHelper(layoutManager)))
outer.add(0)
outer.toIntArray()
} else {
super.calculateDistanceToFinalSnap(layoutManager, targetView)
}
}
override fun findSnapView(layoutManager: RecyclerView.LayoutManager?): View? {
return if (layoutManager is LinearLayoutManager) {
if (layoutManager.canScrollHorizontally()) {
getStartView(layoutManager, getHorizontalHelper(layoutManager))
} else {
super.findSnapView(layoutManager)
}
} else {
super.findSnapView(layoutManager)
}
}
private fun distanceToStart(targetView: View, helper: OrientationHelper): Int {
return helper.getDecoratedStart(targetView) - helper.startAfterPadding
}
private fun getStartView(layoutManager: RecyclerView.LayoutManager, orientationHelper: OrientationHelper): View? {
val firstChild = (layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
val isLastItem = (layoutManager.findLastCompletelyVisibleItemPosition() == layoutManager.itemCount - 1)
if (firstChild == RecyclerView.NO_POSITION || isLastItem) {
return null
}
val child = layoutManager.findViewByPosition(firstChild)
return if (orientationHelper.getDecoratedEnd(child) >= orientationHelper.getDecoratedMeasurement(child) / 2
&& orientationHelper.getDecoratedEnd(child) > 0) {
child;
} else {
if (layoutManager.findFirstCompletelyVisibleItemPosition() == layoutManager.itemCount -1) {
null
} else {
layoutManager.findViewByPosition(firstChild + 1)
}
}
}
private fun getHorizontalHelper(layoutManager: RecyclerView.LayoutManager): OrientationHelper {
return OrientationHelper.createHorizontalHelper(layoutManager)
}
}
I have achieved this function ,we juse need to create a class and extent class LinearSnapHelper and override method CalculateDistanceToFinalSnap and FindSnapView. You can check out the full demo here .
The main code is as follows:
public class StartSnapHelper: LinearSnapHelper
{
private OrientationHelper mVerticalHelper, mHorizontalHelper;
public StartSnapHelper()
{
}
public override void AttachToRecyclerView(RecyclerView recyclerView)
{
base.AttachToRecyclerView(recyclerView);
}
public override int[] CalculateDistanceToFinalSnap(RecyclerView.LayoutManager layoutManager, View targetView)
{
//return base.CalculateDistanceToFinalSnap(layoutManager, targetView);
int[] outer = new int[2];
if (layoutManager.CanScrollHorizontally())
{
outer[0] = distanceToStart(targetView, getHorizontalHelper(layoutManager));
} else {
outer[0] = 0;
}
if (layoutManager.CanScrollVertically()) {
outer[1] = distanceToStart(targetView, getVerticalHelper(layoutManager));
} else {
outer[1] = 0;
}
return outer;
}
private int distanceToStart(View targetView, OrientationHelper helper)
{
return helper.GetDecoratedStart(targetView) - helper.StartAfterPadding;
}
public override View FindSnapView(RecyclerView.LayoutManager layoutManager)
{
if (layoutManager is LinearLayoutManager) {
if (layoutManager.CanScrollHorizontally())
{
return getStartView(layoutManager, getHorizontalHelper(layoutManager));
}
else
{
return getStartView(layoutManager, getVerticalHelper(layoutManager));
}
}
return base.FindSnapView(layoutManager);
}
private View getStartView(RecyclerView.LayoutManager layoutManager,
OrientationHelper helper)
{
if (layoutManager is LinearLayoutManager) {
int firstChild = ((LinearLayoutManager)layoutManager).FindFirstVisibleItemPosition();
bool isLastItem = ((LinearLayoutManager)layoutManager)
.FindLastCompletelyVisibleItemPosition()
== layoutManager.ItemCount - 1;
if (firstChild == RecyclerView.NoPosition || isLastItem)
{
return null;
}
View child = layoutManager.FindViewByPosition(firstChild);
if (helper.GetDecoratedEnd(child) >= helper.GetDecoratedMeasurement(child) / 2
&& helper.GetDecoratedEnd(child) > 0)
{
return child;
}
else
{
if (((LinearLayoutManager)layoutManager).FindLastCompletelyVisibleItemPosition()
== layoutManager.ItemCount - 1)
{
return null;
}
else
{
return layoutManager.FindViewByPosition(firstChild + 1);
}
}
}
return base.FindSnapView(layoutManager);
}
private OrientationHelper getVerticalHelper(RecyclerView.LayoutManager layoutManager)
{
if (mVerticalHelper == null)
{
mVerticalHelper = OrientationHelper.CreateVerticalHelper(layoutManager);
}
return mVerticalHelper;
}
private OrientationHelper getHorizontalHelper(RecyclerView.LayoutManager layoutManager)
{
if (mHorizontalHelper == null)
{
mHorizontalHelper = OrientationHelper.CreateHorizontalHelper(layoutManager);
}
return mHorizontalHelper;
}
}
And use like this:
SnapHelper snapHelperStart = new StartSnapHelper();
snapHelperStart.AttachToRecyclerView(recyclerView);

createUrl doesn't work correctly within extended CBaseUrlRule class

I made my own class that extends CBaseUrlRule to manage some sort of pages on site. Result class code is
class HotelUrlRule extends CBaseUrlRule {
public function parseUrl($manager,$request,$pathInfo,$rawPathInfo) {
if(isset($_GET['id'])) {
if (($_GET['id'] != 0) && ($pathInfo == 'hotel')) {
return 'hotel/index';
}
}
return false;
}
public function createUrl($manager,$route,$params,$ampersand) {
if ($route == 'hotel/index') {
Yii::import('application.controllers.SearchController');
$searcher = new SearchController($this, NULL);
$hotelRaw = $searcher->actionGetHotelInformation($_GET['id']);
$hotelRaw = $hotelRaw['GetHotelInformationResult'];
$hotelName = $hotelRaw['Name'];
$hotelName = preg_replace('%(\s)%', '-', $hotelName);
return 'hotel/' . $hotelName;
}
return false;
}
}
The condition in parseUrl ($_GET['id'] != 0) && ($pathInfo == 'hotel') returns 'true' and the condition in createUrl ($route == 'hotel/index') returns 'false'. Var_dump of $route is 'admin/auth'.
Why is it so? Any guesses?