/* * Copyright (C) 2016 University of South Florida (sjbarbeau@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onebusaway.android.io.test; import org.onebusaway.android.io.elements.ObaRegion; import org.onebusaway.android.mock.MockRegion; import org.onebusaway.android.report.connection.ServiceListTask; import org.onebusaway.android.report.constants.ReportConstants; import org.onebusaway.android.report.ui.util.ServiceUtils; import org.onebusaway.android.util.LocationUtils; import android.location.Location; import android.test.AndroidTestCase; import android.text.TextUtils; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import edu.usf.cutr.open311client.Open311; import edu.usf.cutr.open311client.Open311Manager; import edu.usf.cutr.open311client.models.Open311Option; import edu.usf.cutr.open311client.models.Service; import edu.usf.cutr.open311client.models.ServiceListRequest; import edu.usf.cutr.open311client.models.ServiceListResponse; /** * Tests to evaluate interactions with Open311 system for regions that use Open311. * * NOTE: These tests make actual HTTP requests to live Open311 servers (SeeClickFix), because we * make some assumptions required for text heuristic matching to identify transit-related services. * If there are changes in the live server (e.g., new services added than aren't transit-related * but include some of the text we're using to identify transit services), these could break our * assumptions, and we want to know about that. */ public class ReportProblemOpen311Test extends AndroidTestCase { // Mock region to use in tests ObaRegion mTampaRegion; @Override protected void setUp() throws Exception { super.setUp(); mTampaRegion = MockRegion.getTampa(getContext()); // Clear all open311 endpoints Open311Manager.clearOpen311(); assertNotNull(mTampaRegion.getOpen311Servers()); // Read the open311 preferences from the region and set if (mTampaRegion.getOpen311Servers() != null) { for (ObaRegion.Open311Server open311Server : mTampaRegion.getOpen311Servers()) { String jurisdictionId = open311Server.getJuridisctionId(); Open311Option option = new Open311Option(open311Server.getBaseUrl(), open311Server.getApiKey(), TextUtils.isEmpty(jurisdictionId) ? null : jurisdictionId); Open311Manager.initOpen311WithOption(option); } } } /** * Tests locations in Hillsborough County for services at that location. There should be at * least * ReportConstants.NUM_TRANSIT_SERVICES_THRESHOLD services marked as transit services, as HART * is the primary SeeClickFix account holder and therefore all services are transit-related. * As of Dec. 2, 2016 services are heuristically matched based on text in the service name * (SeeClickFix does not support the group or keyword Open311 elements for explicit matching). */ public void testHillsboroughCounty() { List<Location> locations = new ArrayList<>(); // USF area locations.add(LocationUtils.makeLocation(28.0612088, -82.415747)); // Downtown locations.add(LocationUtils.makeLocation(27.9577463, -82.4559472)); // Brandon locations.add(LocationUtils.makeLocation(27.9520925, -82.3039963)); List<Service> serviceList = _testOpen311AtLocation(locations); // Make sure we get a valid response here - a failure could be intermittent network issues assertNotNull(serviceList); // Mark the services that are transit-related boolean mIsAllTransitHeuristicMatch = ServiceUtils .markTransitServices(getContext(), serviceList); assertTrue(mIsAllTransitHeuristicMatch); int countGroupTransit = 0; int countDynamicStop = 0; int countDynamicTrip = 0; for (Service s : serviceList) { if (s.getGroup().equals(ReportConstants.ISSUE_GROUP_TRANSIT)) { countGroupTransit++; } if (s.getType().equals(ReportConstants.DYNAMIC_TRANSIT_SERVICE_STOP)) { countDynamicStop++; } if (s.getType().equals(ReportConstants.DYNAMIC_TRANSIT_SERVICE_TRIP)) { countDynamicTrip++; } } // We should be over the threshold of assuming that all services (request types) are transit-related assertTrue(countGroupTransit >= ReportConstants.NUM_TRANSIT_SERVICES_THRESHOLD); // Everything not arrival times related should be marked as dynamic stop assertTrue(countDynamicStop >= ReportConstants.NUM_TRANSIT_SERVICES_THRESHOLD); // There should only be one arrival times (trip) request type, because we treat that differently (show arrivals to pick from) assertTrue(countDynamicTrip == 1); } /** * Tests locations in Pinellas County for services at that location. There should be less than * ReportConstants.NUM_TRANSIT_SERVICES_THRESHOLD services marked as transit services, because * PSTA has only 2 (stop problem and arrival time problem) of the many services maintained * by Pinellas County. As of Dec. 2, 2016 services are heuristically matched based on text in * the service name (SeeClickFix does not support the group or keyword Open311 elements for * explicit matching). */ public void testPinellasCounty() { List<Location> locations = new ArrayList<>(); // Mid County locations.add(LocationUtils.makeLocation(27.8435877, -82.7109945)); // St. Pete locations.add(LocationUtils.makeLocation(27.7626097, -82.6436986)); // Largo locations.add(LocationUtils.makeLocation(27.9118406, -82.7879116)); // Clearwater locations.add(LocationUtils.makeLocation(27.9632576, -82.7885631)); List<Service> serviceList = _testOpen311AtLocation(locations); // Make sure we get a valid response here - a failure could be intermittent network issues assertNotNull(serviceList); // Mark the services that are transit-related boolean mIsAllTransitHeuristicMatch = ServiceUtils .markTransitServices(getContext(), serviceList); assertFalse(mIsAllTransitHeuristicMatch); // There should be less than ReportConstants.NUM_TRANSIT_SERVICES_THRESHOLD services // marked as transit services in Pinellas County int countGroupTransit = 0; int countDynamicStop = 0; int countDynamicTrip = 0; for (Service s : serviceList) { if (s.getGroup() != null && s.getGroup().equals(ReportConstants.ISSUE_GROUP_TRANSIT)) { countGroupTransit++; } if (s.getType().equals(ReportConstants.DYNAMIC_TRANSIT_SERVICE_STOP)) { countDynamicStop++; } if (s.getType().equals(ReportConstants.DYNAMIC_TRANSIT_SERVICE_TRIP)) { countDynamicTrip++; } } // We should be under the threshold for assuming that all services as transit-related assertTrue(countGroupTransit < ReportConstants.NUM_TRANSIT_SERVICES_THRESHOLD); // We should only recognize two transit request types (services) - stop and trip assertTrue(countDynamicStop == 1); assertTrue(countDynamicTrip == 1); } private List<Service> _testOpen311AtLocation(List<Location> locations) { for (Location l : locations) { ServiceListRequest slr = new ServiceListRequest(l.getLatitude(), l.getLongitude()); List<Open311> open311List = Open311Manager.getAllOpen311(); ServiceListTask.Callback callback = new ServiceListTask.Callback() { @Override public void onServicesTaskCompleted(ServiceListResponse services, Open311 open311) { } }; ServiceListTask serviceListTask = new ServiceListTask(slr, open311List, callback); try { // Execute the AsyncTask synchronously ServiceListResponse services = serviceListTask.execute().get(); List<Service> serviceList = new ArrayList<>(); // Add services to list if service response is successful if (services != null && services.isSuccess() && Open311Manager.isAreaManagedByOpen311(services.getServiceList())) { for (Service s : services.getServiceList()) { if (s.getService_name() != null && s.getService_code() != null) { serviceList.add(s); } } } return serviceList; } catch (InterruptedException | ExecutionException e) { // Print any network errors e.printStackTrace(); } } return null; } }