1180360409c9e4e9163c670ff48663244b4057eafMaurice Lam/* 2180360409c9e4e9163c670ff48663244b4057eafMaurice Lam * Copyright (C) 2015 The Android Open Source Project 3180360409c9e4e9163c670ff48663244b4057eafMaurice Lam * 4180360409c9e4e9163c670ff48663244b4057eafMaurice Lam * Licensed under the Apache License, Version 2.0 (the "License"); 5180360409c9e4e9163c670ff48663244b4057eafMaurice Lam * you may not use this file except in compliance with the License. 6180360409c9e4e9163c670ff48663244b4057eafMaurice Lam * You may obtain a copy of the License at 7180360409c9e4e9163c670ff48663244b4057eafMaurice Lam * 8180360409c9e4e9163c670ff48663244b4057eafMaurice Lam * http://www.apache.org/licenses/LICENSE-2.0 9180360409c9e4e9163c670ff48663244b4057eafMaurice Lam * 10180360409c9e4e9163c670ff48663244b4057eafMaurice Lam * Unless required by applicable law or agreed to in writing, software 11180360409c9e4e9163c670ff48663244b4057eafMaurice Lam * distributed under the License is distributed on an "AS IS" BASIS, 12180360409c9e4e9163c670ff48663244b4057eafMaurice Lam * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13180360409c9e4e9163c670ff48663244b4057eafMaurice Lam * See the License for the specific language governing permissions and 14180360409c9e4e9163c670ff48663244b4057eafMaurice Lam * limitations under the License. 15180360409c9e4e9163c670ff48663244b4057eafMaurice Lam */ 16180360409c9e4e9163c670ff48663244b4057eafMaurice Lam 17180360409c9e4e9163c670ff48663244b4057eafMaurice Lampackage com.android.setupwizardlib.test; 18180360409c9e4e9163c670ff48663244b4057eafMaurice Lam 192614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lamimport static org.junit.Assert.assertEquals; 202614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lamimport static org.junit.Assert.assertSame; 212614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lam 222614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lamimport android.content.Context; 23180360409c9e4e9163c670ff48663244b4057eafMaurice Lamimport android.graphics.Bitmap; 24180360409c9e4e9163c670ff48663244b4057eafMaurice Lamimport android.graphics.Canvas; 25180360409c9e4e9163c670ff48663244b4057eafMaurice Lamimport android.graphics.Color; 26180360409c9e4e9163c670ff48663244b4057eafMaurice Lamimport android.graphics.Paint; 27efd346d200a1649d94c5a1add1636de5b7d56eefUdam Sainiimport android.graphics.PorterDuff; 28efd346d200a1649d94c5a1add1636de5b7d56eefUdam Sainiimport android.graphics.PorterDuffXfermode; 29180360409c9e4e9163c670ff48663244b4057eafMaurice Lamimport android.graphics.drawable.ColorDrawable; 30180360409c9e4e9163c670ff48663244b4057eafMaurice Lamimport android.graphics.drawable.Drawable; 312614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lamimport android.support.test.InstrumentationRegistry; 322614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lamimport android.support.test.filters.SmallTest; 332614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lamimport android.support.test.runner.AndroidJUnit4; 34180360409c9e4e9163c670ff48663244b4057eafMaurice Lamimport android.support.v7.widget.LinearLayoutManager; 35180360409c9e4e9163c670ff48663244b4057eafMaurice Lamimport android.support.v7.widget.RecyclerView; 36180360409c9e4e9163c670ff48663244b4057eafMaurice Lamimport android.view.View; 37180360409c9e4e9163c670ff48663244b4057eafMaurice Lamimport android.view.ViewGroup; 38180360409c9e4e9163c670ff48663244b4057eafMaurice Lam 39180360409c9e4e9163c670ff48663244b4057eafMaurice Lamimport com.android.setupwizardlib.DividerItemDecoration; 40180360409c9e4e9163c670ff48663244b4057eafMaurice Lam 412614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lamimport org.junit.Test; 422614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lamimport org.junit.runner.RunWith; 432614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lam 442614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lam@RunWith(AndroidJUnit4.class) 452614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lam@SmallTest 462614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lampublic class DividerItemDecorationTest { 47180360409c9e4e9163c670ff48663244b4057eafMaurice Lam 482614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lam @Test 49180360409c9e4e9163c670ff48663244b4057eafMaurice Lam public void testDivider() { 50180360409c9e4e9163c670ff48663244b4057eafMaurice Lam final DividerItemDecoration decoration = new DividerItemDecoration(); 51180360409c9e4e9163c670ff48663244b4057eafMaurice Lam Drawable divider = new ColorDrawable(); 52180360409c9e4e9163c670ff48663244b4057eafMaurice Lam decoration.setDivider(divider); 53180360409c9e4e9163c670ff48663244b4057eafMaurice Lam assertSame("Divider should be same as set", divider, decoration.getDivider()); 54180360409c9e4e9163c670ff48663244b4057eafMaurice Lam } 55180360409c9e4e9163c670ff48663244b4057eafMaurice Lam 562614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lam @Test 57180360409c9e4e9163c670ff48663244b4057eafMaurice Lam public void testDividerHeight() { 58180360409c9e4e9163c670ff48663244b4057eafMaurice Lam final DividerItemDecoration decoration = new DividerItemDecoration(); 59180360409c9e4e9163c670ff48663244b4057eafMaurice Lam decoration.setDividerHeight(123); 60180360409c9e4e9163c670ff48663244b4057eafMaurice Lam assertEquals("Divider height should be 123", 123, decoration.getDividerHeight()); 61180360409c9e4e9163c670ff48663244b4057eafMaurice Lam } 62180360409c9e4e9163c670ff48663244b4057eafMaurice Lam 632614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lam @Test 64efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini public void testShouldDrawDividerBelowWithEitherCondition() { 65180360409c9e4e9163c670ff48663244b4057eafMaurice Lam // Set up the item decoration, with 1px red divider line 66180360409c9e4e9163c670ff48663244b4057eafMaurice Lam final DividerItemDecoration decoration = new DividerItemDecoration(); 67180360409c9e4e9163c670ff48663244b4057eafMaurice Lam Drawable divider = new ColorDrawable(Color.RED); 68180360409c9e4e9163c670ff48663244b4057eafMaurice Lam decoration.setDivider(divider); 69180360409c9e4e9163c670ff48663244b4057eafMaurice Lam decoration.setDividerHeight(1); 70180360409c9e4e9163c670ff48663244b4057eafMaurice Lam 71efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini Bitmap bitmap = drawDecoration(decoration, true, true); 72efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 73efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini // Draw the expected result on a bitmap 74efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini Bitmap expectedBitmap = Bitmap.createBitmap(20, 20, Bitmap.Config.ARGB_4444); 75efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini Canvas expectedCanvas = new Canvas(expectedBitmap); 76efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini Paint paint = new Paint(); 77efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini paint.setColor(Color.RED); 78efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini expectedCanvas.drawRect(0, 5, 20, 6, paint); 79efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini expectedCanvas.drawRect(0, 10, 20, 11, paint); 80efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini expectedCanvas.drawRect(0, 15, 20, 16, paint); 81efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini // Compare the two bitmaps 82efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini assertBitmapEquals(expectedBitmap, bitmap); 83efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 84efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini bitmap.recycle(); 85efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini bitmap = drawDecoration(decoration, false, true); 86efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini // should still be the same. 87efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini assertBitmapEquals(expectedBitmap, bitmap); 88efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 89efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini bitmap.recycle(); 90efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini bitmap = drawDecoration(decoration, true, false); 91efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini // last item should not have a divider below it now 92efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini paint.setColor(Color.TRANSPARENT); 93efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 94efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini expectedCanvas.drawRect(0, 15, 20, 16, paint); 95efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini assertBitmapEquals(expectedBitmap, bitmap); 96efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 97efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini bitmap.recycle(); 98efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini bitmap = drawDecoration(decoration, false, false); 99efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini // everything should be transparent now 100efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini expectedCanvas.drawRect(0, 5, 20, 6, paint); 101efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini expectedCanvas.drawRect(0, 10, 20, 11, paint); 102efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini assertBitmapEquals(expectedBitmap, bitmap); 103efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 104efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini } 105efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 1062614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lam @Test 107efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini public void testShouldDrawDividerBelowWithBothCondition() { 108efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini // Set up the item decoration, with 1px green divider line 109efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini final DividerItemDecoration decoration = new DividerItemDecoration(); 110efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini Drawable divider = new ColorDrawable(Color.GREEN); 111efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini decoration.setDivider(divider); 112efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini decoration.setDividerHeight(1); 113efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini decoration.setDividerCondition(DividerItemDecoration.DIVIDER_CONDITION_BOTH); 114efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 115efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini Bitmap bitmap = drawDecoration(decoration, true, true); 116efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini Paint paint = new Paint(); 117efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini paint.setColor(Color.GREEN); 118efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD)); 119efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini Bitmap expectedBitmap = Bitmap.createBitmap(20, 20, Bitmap.Config.ARGB_4444); 120efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini Canvas expectedCanvas = new Canvas(expectedBitmap); 121efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini expectedCanvas.drawRect(0, 5, 20, 6, paint); 122efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini expectedCanvas.drawRect(0, 10, 20, 11, paint); 123efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini expectedCanvas.drawRect(0, 15, 20, 16, paint); 124efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini // Should have all the dividers 125efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini assertBitmapEquals(expectedBitmap, bitmap); 126efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 127efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini bitmap.recycle(); 128efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini bitmap = drawDecoration(decoration, false, true); 129efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini paint.setColor(Color.TRANSPARENT); 130efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 131efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini expectedCanvas.drawRect(0, 5, 20, 6, paint); 132efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini expectedCanvas.drawRect(0, 10, 20, 11, paint); 133efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini assertBitmapEquals(expectedBitmap, bitmap); 134efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 135efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini bitmap.recycle(); 136efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini bitmap = drawDecoration(decoration, true, false); 137efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini // nothing should be drawn now. 138efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini expectedCanvas.drawRect(0, 15, 20, 16, paint); 139efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini assertBitmapEquals(expectedBitmap, bitmap); 140efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 141efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini bitmap.recycle(); 142efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini bitmap = drawDecoration(decoration, false, false); 143efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini assertBitmapEquals(expectedBitmap, bitmap); 144efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini } 145efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 146efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini private Bitmap drawDecoration(DividerItemDecoration decoration, final boolean allowDividerAbove, 147efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini final boolean allowDividerBelow) { 148efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini // Set up the canvas to be drawn 149efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini Bitmap bitmap = Bitmap.createBitmap(20, 20, Bitmap.Config.ARGB_4444); 150efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini Canvas canvas = new Canvas(bitmap); 151efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 1522614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lam final Context context = InstrumentationRegistry.getContext(); 153180360409c9e4e9163c670ff48663244b4057eafMaurice Lam // Set up recycler view with vertical linear layout manager 1542614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lam RecyclerView testRecyclerView = new RecyclerView(context); 1552614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lam testRecyclerView.setLayoutManager(new LinearLayoutManager(context)); 156180360409c9e4e9163c670ff48663244b4057eafMaurice Lam 157180360409c9e4e9163c670ff48663244b4057eafMaurice Lam // Set up adapter with 3 items, each 5px tall 158180360409c9e4e9163c670ff48663244b4057eafMaurice Lam testRecyclerView.setAdapter(new RecyclerView.Adapter() { 159180360409c9e4e9163c670ff48663244b4057eafMaurice Lam @Override 160180360409c9e4e9163c670ff48663244b4057eafMaurice Lam public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { 1612614260933341bd4ea7bb37a3435f46f82cacef7Maurice Lam final View itemView = new View(context); 162180360409c9e4e9163c670ff48663244b4057eafMaurice Lam itemView.setMinimumWidth(20); 163180360409c9e4e9163c670ff48663244b4057eafMaurice Lam itemView.setMinimumHeight(5); 164efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini return ViewHolder.createInstance(itemView, allowDividerAbove, allowDividerBelow); 165180360409c9e4e9163c670ff48663244b4057eafMaurice Lam } 166180360409c9e4e9163c670ff48663244b4057eafMaurice Lam 167180360409c9e4e9163c670ff48663244b4057eafMaurice Lam @Override 168180360409c9e4e9163c670ff48663244b4057eafMaurice Lam public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) { 169180360409c9e4e9163c670ff48663244b4057eafMaurice Lam } 170180360409c9e4e9163c670ff48663244b4057eafMaurice Lam 171180360409c9e4e9163c670ff48663244b4057eafMaurice Lam @Override 172180360409c9e4e9163c670ff48663244b4057eafMaurice Lam public int getItemCount() { 173180360409c9e4e9163c670ff48663244b4057eafMaurice Lam return 3; 174180360409c9e4e9163c670ff48663244b4057eafMaurice Lam } 175180360409c9e4e9163c670ff48663244b4057eafMaurice Lam }); 176180360409c9e4e9163c670ff48663244b4057eafMaurice Lam 177180360409c9e4e9163c670ff48663244b4057eafMaurice Lam testRecyclerView.layout(0, 0, 20, 20); 178180360409c9e4e9163c670ff48663244b4057eafMaurice Lam decoration.onDraw(canvas, testRecyclerView, null); 179efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini return bitmap; 180180360409c9e4e9163c670ff48663244b4057eafMaurice Lam } 181180360409c9e4e9163c670ff48663244b4057eafMaurice Lam 182180360409c9e4e9163c670ff48663244b4057eafMaurice Lam private void assertBitmapEquals(Bitmap expected, Bitmap actual) { 183180360409c9e4e9163c670ff48663244b4057eafMaurice Lam assertEquals("Width should be the same", expected.getWidth(), actual.getWidth()); 184180360409c9e4e9163c670ff48663244b4057eafMaurice Lam assertEquals("Height should be the same", expected.getHeight(), actual.getHeight()); 185180360409c9e4e9163c670ff48663244b4057eafMaurice Lam for (int x = 0; x < expected.getWidth(); x++) { 186180360409c9e4e9163c670ff48663244b4057eafMaurice Lam for (int y = 0; y < expected.getHeight(); y++) { 187180360409c9e4e9163c670ff48663244b4057eafMaurice Lam assertEquals("Pixel at (" + x + ", " + y + ") should be the same", 188180360409c9e4e9163c670ff48663244b4057eafMaurice Lam expected.getPixel(x, y), actual.getPixel(x, y)); 189180360409c9e4e9163c670ff48663244b4057eafMaurice Lam } 190180360409c9e4e9163c670ff48663244b4057eafMaurice Lam } 191180360409c9e4e9163c670ff48663244b4057eafMaurice Lam } 192efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 193efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini private static class ViewHolder extends RecyclerView.ViewHolder 194efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini implements DividerItemDecoration.DividedViewHolder { 195efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 196efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini private boolean mAllowDividerAbove; 197efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini private boolean mAllowDividerBelow; 198efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 199efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini public static ViewHolder createInstance(View itemView, boolean allowDividerAbove, 200efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini boolean allowDividerBelow) { 201efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini return new ViewHolder(itemView, allowDividerAbove, allowDividerBelow); 202efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini } 203efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 204efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini private ViewHolder(View itemView, boolean allowDividerAbove, boolean allowDividerBelow) { 205efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini super(itemView); 206efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini mAllowDividerAbove = allowDividerAbove; 207efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini mAllowDividerBelow = allowDividerBelow; 208efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini } 209efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 210efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini @Override 211efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini public boolean isDividerAllowedAbove() { 212efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini return mAllowDividerAbove; 213efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini } 214efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini 215efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini @Override 216efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini public boolean isDividerAllowedBelow() { 217efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini return mAllowDividerBelow; 218efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini } 219efd346d200a1649d94c5a1add1636de5b7d56eefUdam Saini } 220180360409c9e4e9163c670ff48663244b4057eafMaurice Lam} 221