1 /*
2  * Copyright (C) 2023 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 package com.android.launcher3.celllayout;
17 
18 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
19 
20 import android.graphics.Point;
21 
22 import java.io.BufferedReader;
23 import java.io.IOException;
24 import java.io.InputStreamReader;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Locale;
30 import java.util.stream.Collectors;
31 
32 public class CellLayoutTestCaseReader {
33 
34     public abstract static class TestSection {
35         State state;
36 
TestSection(State state)37         public TestSection(State state) {
38             this.state = state;
39         }
40 
getState()41         public State getState() {
42             return state;
43         }
44 
setState(State state)45         public void setState(State state) {
46             this.state = state;
47         }
48     }
49 
50     public static class Comment extends TestSection {
Comment()51         public Comment() {
52             super(State.COMMENT);
53         }
54     }
55 
56     public static class Arguments extends TestSection {
57         String[] arguments;
58 
Arguments(String[] arguments)59         public Arguments(String[] arguments) {
60             super(State.ARGUMENTS);
61             this.arguments = arguments;
62         }
63     }
64 
65     public static class Board extends TestSection {
66         public Point gridSize;
67         public String board;
68 
Board(Point gridSize, String board)69         public Board(Point gridSize, String board) {
70             super(State.BOARD);
71             this.gridSize = gridSize;
72             this.board = board;
73         }
74     }
75 
76     public enum State {
77         START,
78         ARGUMENTS,
79         BOARD,
80         END,
81         COMMENT
82     }
83 
84     String mTest;
85 
CellLayoutTestCaseReader(String test)86     protected CellLayoutTestCaseReader(String test) {
87         mTest = test;
88     }
89 
readFromFile(String fileName)90     public static CellLayoutTestCaseReader readFromFile(String fileName) throws IOException {
91         String fileStr = new BufferedReader(new InputStreamReader(
92                 getInstrumentation().getContext().getAssets().open(fileName))
93         ).lines().collect(Collectors.joining("\n"));
94         return new CellLayoutTestCaseReader(fileStr);
95     }
96 
getStateFromLine(String line)97     private State getStateFromLine(String line) {
98         String typeWithColons = line.trim().split(" ")[0].trim();
99         String type = typeWithColons.substring(0, typeWithColons.length() - 1);
100         try {
101             return Enum.valueOf(State.class, type.toUpperCase());
102         } catch (Exception e) {
103             throw new RuntimeException(
104                     "The given tag " + typeWithColons + " doesn't match with the existing tags");
105         }
106     }
107 
removeTag(String line)108     private String removeTag(String line) {
109         return line.split(":")[1];
110     }
111 
parseNextLine(Iterator<String> it)112     private TestSection parseNextLine(Iterator<String> it) {
113         String line = it.next();
114         if (line.trim().charAt(0) == '#') {
115             return new Comment();
116         }
117         State state = getStateFromLine(line);
118         line = removeTag(line);
119         switch (state) {
120             case ARGUMENTS:
121                 return new Arguments(parseArgumentsLine(line));
122             case BOARD:
123                 Point grid = parseGridSize(line);
124                 return new Board(grid, parseBoard(it, grid.y));
125             default:
126                 return new Comment();
127         }
128     }
129 
parse()130     public List<TestSection> parse() {
131         List<TestSection> sections = new ArrayList<>();
132         String[] lines = mTest.split("\n");
133         Iterator<String> it = Arrays.stream(lines).iterator();
134         while (it.hasNext()) {
135             TestSection section = parseNextLine(it);
136             if (section.state == State.COMMENT) {
137                 continue;
138             }
139             sections.add(section);
140         }
141         return sections;
142     }
143 
parseBoard(Iterator<String> it, int rows)144     private String parseBoard(Iterator<String> it, int rows) {
145         StringBuilder board = new StringBuilder();
146         for (int j = 0; j < rows; j++) {
147             board.append(it.next() + "\n");
148         }
149         return board.toString();
150     }
151 
parseArgumentsLine(String line)152     private String[] parseArgumentsLine(String line) {
153         return Arrays.stream(line.trim().split(" ")).map(String::trim).toArray(String[]::new);
154     }
155 
parseGridSize(String line)156     private Point parseGridSize(String line) {
157         String[] values = line.toLowerCase(Locale.ROOT).split("x");
158         int x = Integer.parseInt(values[0].trim());
159         int y = Integer.parseInt(values[1].trim());
160         return new Point(x, y);
161     }
162 }
163