/* * (C) Copyright IBM Corp. 2019, 2020. * * 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 com.ibm.watson.visual_recognition.v3; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import com.google.common.io.Files; import com.google.gson.Gson; import com.google.gson.JsonObject; import com.ibm.cloud.sdk.core.http.HttpMediaType; import com.ibm.cloud.sdk.core.security.NoAuthAuthenticator; import com.ibm.watson.common.WatsonServiceUnitTest; import com.ibm.watson.visual_recognition.v3.model.ClassifiedImages; import com.ibm.watson.visual_recognition.v3.model.Classifier; import com.ibm.watson.visual_recognition.v3.model.ClassifyOptions; import com.ibm.watson.visual_recognition.v3.model.CreateClassifierOptions; import com.ibm.watson.visual_recognition.v3.model.DeleteClassifierOptions; import com.ibm.watson.visual_recognition.v3.model.DeleteUserDataOptions; import com.ibm.watson.visual_recognition.v3.model.GetClassifierOptions; import com.ibm.watson.visual_recognition.v3.model.GetCoreMlModelOptions; import com.ibm.watson.visual_recognition.v3.model.ListClassifiersOptions; import com.ibm.watson.visual_recognition.v3.model.UpdateClassifierOptions; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.RecordedRequest; import okio.Buffer; import org.junit.Before; import org.junit.Test; /** Unit tests for the {@link VisualRecognition} service. */ public class VisualRecognitionTest extends WatsonServiceUnitTest { private static final String FIXTURE_CLASSIFICATION = "src/test/resources/visual_recognition/v3/visual_classification.json"; private static final String FIXTURE_CLASSIFIER = "src/test/resources/visual_recognition/v3/visual_classifier.json"; private static final String IMAGE_FILE = "src/test/resources/visual_recognition/v3/test.zip"; private static final String SINGLE_IMAGE_FILE = "src/test/resources/visual_recognition/v3/car.png"; private static final String PATH_CLASSIFY = "/v3/classify"; private static final String VERSION_KEY = "version"; private static final String VERSION = "2018-03-19"; private static final String PATH_CLASSIFIERS = "/v3/classifiers"; private static final String PATH_CLASSIFIER = "/v3/classifiers/%s"; private static final String PATH_CORE_ML = "/v3/classifiers/%s/core_ml_model"; private static final String FILENAME = "test_file"; private VisualRecognition service; /** * Sets up the tests. * * @throws Exception the exception */ /* * (non-Javadoc) * @see com.ibm.watson.common.WatsonServiceUnitTest#setUp() */ @Override @Before public void setUp() throws Exception { super.setUp(); service = new VisualRecognition(VERSION, new NoAuthAuthenticator()); service.setServiceUrl(getMockWebServerUrl()); } /** * Test classify with file. * * @throws IOException Signals that an I/O exception has occurred. * @throws InterruptedException the interrupted exception */ @Test public void testClassifyWithFile() throws IOException, InterruptedException { ClassifiedImages mockResponse = loadFixture(FIXTURE_CLASSIFICATION, ClassifiedImages.class); server.enqueue(new MockResponse().setBody(mockResponse.toString())); // execute request File images = new File(IMAGE_FILE); ClassifyOptions options = new ClassifyOptions.Builder() .imagesFile(images) .classifierIds(Collections.singletonList("car")) .build(); ClassifiedImages serviceResponse = service.classify(options).execute().getResult(); // first request RecordedRequest request = server.takeRequest(); String path = PATH_CLASSIFY + "?" + VERSION_KEY + "=" + VERSION; assertEquals(path, request.getPath()); assertEquals("POST", request.getMethod()); assertEquals(serviceResponse, mockResponse); } /** * Test classify with bytes or stream. * * @throws IOException Signals that an I/O exception has occurred. * @throws InterruptedException the interrupted exception */ @Test public void testClassifyWithBytes() throws IOException, InterruptedException { ClassifiedImages mockResponse = loadFixture(FIXTURE_CLASSIFICATION, ClassifiedImages.class); server.enqueue(new MockResponse().setBody(mockResponse.toString())); // execute request File images = new File(SINGLE_IMAGE_FILE); InputStream fileStream = new FileInputStream(images); ClassifyOptions options = new ClassifyOptions.Builder() .imagesFile(fileStream) .imagesFilename(FILENAME) .classifierIds(Collections.singletonList("car")) .build(); ClassifiedImages serviceResponse = service.classify(options).execute().getResult(); // first request RecordedRequest request = server.takeRequest(); String path = PATH_CLASSIFY + "?" + VERSION_KEY + "=" + VERSION; assertEquals(path, request.getPath()); assertEquals("POST", request.getMethod()); assertEquals(serviceResponse, mockResponse); } /** * Test update classifier. * * @throws IOException Signals that an I/O exception has occurred. * @throws InterruptedException the interrupted exception */ @Test public void testUpdateClassifier() throws IOException, InterruptedException { Classifier mockResponse = loadFixture(FIXTURE_CLASSIFIER, Classifier.class); server.enqueue(new MockResponse().setBody(mockResponse.toString())); // execute request File images = new File(IMAGE_FILE); String class1 = "class1"; String classifierId = "foo123"; UpdateClassifierOptions options = new UpdateClassifierOptions.Builder(classifierId) .addPositiveExamples(class1, images) .build(); Classifier serviceResponse = service.updateClassifier(options).execute().getResult(); // first request String path = String.format(PATH_CLASSIFIER, classifierId); RecordedRequest request = server.takeRequest(); path += "?" + VERSION_KEY + "=" + VERSION; assertEquals(path, request.getPath()); assertEquals("POST", request.getMethod()); String body = request.getBody().readUtf8(); String contentDisposition = "Content-Disposition: form-data; name=\"class1_positive_examples\";"; assertTrue(body.contains(contentDisposition)); assertTrue(!body.contains("Content-Disposition: form-data; name=\"name\"")); assertEquals(serviceResponse, mockResponse); } /** * Test create classifier. * * @throws IOException Signals that an I/O exception has occurred. * @throws InterruptedException the interrupted exception */ @Test public void testCreateClassifier() throws IOException, InterruptedException { Classifier mockResponse = loadFixture(FIXTURE_CLASSIFIER, Classifier.class); server.enqueue(new MockResponse().setBody(mockResponse.toString())); // execute request File positiveImages = new File(IMAGE_FILE); File negativeImages = new File(IMAGE_FILE); String class1 = "class1"; CreateClassifierOptions options = new CreateClassifierOptions.Builder() .name(class1) .addPositiveExamples(class1, positiveImages) .negativeExamples(negativeImages) .build(); Classifier serviceResponse = service.createClassifier(options).execute().getResult(); // first request RecordedRequest request = server.takeRequest(); String path = PATH_CLASSIFIERS + "?" + VERSION_KEY + "=" + VERSION; assertEquals(path, request.getPath()); assertEquals("POST", request.getMethod()); String body = request.getBody().readUtf8(); String contentDisposition = "Content-Disposition: form-data; name=\"class1_positive_examples\";"; assertTrue(body.contains(contentDisposition)); assertTrue(body.contains("Content-Disposition: form-data; name=\"name\"")); assertEquals(serviceResponse, mockResponse); } /** * Test delete classifier. * * @throws IOException Signals that an I/O exception has occurred. * @throws InterruptedException the interrupted exception */ @Test public void testDeleteClassifier() throws IOException, InterruptedException { server.enqueue(new MockResponse().setBody("")); String class1 = "class1"; DeleteClassifierOptions options = new DeleteClassifierOptions.Builder(class1).build(); service.deleteClassifier(options).execute(); // first request RecordedRequest request = server.takeRequest(); String path = String.format(PATH_CLASSIFIER + "?" + VERSION_KEY + "=" + VERSION, class1); assertEquals(path, request.getPath()); assertEquals("DELETE", request.getMethod()); } /** * Test get classifier. * * @throws InterruptedException the interrupted exception * @throws IOException Signals that an I/O exception has occurred. */ @Test public void testGetClassifier() throws InterruptedException, IOException { try { Classifier mockResponse = loadFixture(FIXTURE_CLASSIFIER, Classifier.class); server.enqueue(new MockResponse().setBody(mockResponse.toString())); // execute request String class1 = "class1"; GetClassifierOptions getOptions = new GetClassifierOptions.Builder(class1).build(); Classifier serviceResponse = service.getClassifier(getOptions).execute().getResult(); // first request RecordedRequest request = server.takeRequest(); String path = String.format(PATH_CLASSIFIER + "?" + VERSION_KEY + "=" + VERSION, class1); assertEquals(path, request.getPath()); assertEquals("GET", request.getMethod()); assertEquals(serviceResponse, mockResponse); } catch (Exception e) { e.printStackTrace(); } } /** * Test get classifiers. * * @throws InterruptedException the interrupted exception * @throws IOException Signals that an I/O exception has occurred. */ @Test public void testGetClassifiers() throws InterruptedException, IOException { Classifier mockClassifier = loadFixture(FIXTURE_CLASSIFIER, Classifier.class); List<Classifier> classifiers = new ArrayList<>(); classifiers.add(mockClassifier); classifiers.add(mockClassifier); classifiers.add(mockClassifier); JsonObject mockResponse = new JsonObject(); mockResponse.add("classifiers", new Gson().toJsonTree(classifiers)); server.enqueue(new MockResponse().setBody(mockResponse.toString())); ListClassifiersOptions options = new ListClassifiersOptions.Builder().verbose(true).build(); List<Classifier> serviceResponse = service.listClassifiers(options).execute().getResult().getClassifiers(); // first request RecordedRequest request = server.takeRequest(); String path = PATH_CLASSIFIERS + "?" + VERSION_KEY + "=" + VERSION + "&verbose=true"; assertEquals(path, request.getPath()); assertEquals("GET", request.getMethod()); assertEquals(serviceResponse, classifiers); } /** * Test get core ml model. * * @throws IOException Signals that an I/O exception has occurred. * @throws InterruptedException the interrupted exception */ @Test public void testGetCoreMlModel() throws IOException, InterruptedException { final File model = new File("src/test/resources/visual_recognition/v3/custom_model.mlmodel"); @SuppressWarnings("resource") final Buffer buffer = new Buffer().write(Files.toByteArray(model)); server.enqueue( new MockResponse() .addHeader(CONTENT_TYPE, HttpMediaType.APPLICATION_OCTET_STREAM) .setBody(buffer)); String classifierId = "classifier_id"; GetCoreMlModelOptions options = new GetCoreMlModelOptions.Builder().classifierId(classifierId).build(); InputStream modelFile = service.getCoreMlModel(options).execute().getResult(); RecordedRequest request = server.takeRequest(); String path = String.format(PATH_CORE_ML, classifierId) + "?" + VERSION_KEY + "=" + VERSION; assertEquals(path, request.getPath()); assertEquals("GET", request.getMethod()); File outputFile = new File("src/test/resources/visual_recognition/v3/model_result.mlmodel"); outputFile.createNewFile(); writeInputStreamToFile(modelFile, outputFile); } /** Test delete user data options builder. */ @Test public void testDeleteUserDataOptionsBuilder() { String customerId = "java_sdk_test_id"; DeleteUserDataOptions deleteOptions = new DeleteUserDataOptions.Builder().customerId(customerId).build(); assertEquals(deleteOptions.customerId(), customerId); } }