Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 04a7e0a7 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Generate license html file from xml files of partitions"

parents 7baae2a9 fa0242c2
Loading
Loading
Loading
Loading
+292 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * 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.android.settings;

import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.util.Log;
import android.util.Xml;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;

/**
 * The utility class that generate a license html file from xml files.
 * All the HTML snippets and logic are copied from build/make/tools/generate-notice-files.py.
 *
 * TODO: Remove duplicate codes once backward support ends.
 */
class LicenseHtmlGeneratorFromXml {
    private static final String TAG = "LicenseHtmlGeneratorFromXml";

    private static final String TAG_ROOT = "licenses";
    private static final String TAG_FILE_NAME = "file-name";
    private static final String TAG_FILE_CONTENT = "file-content";
    private static final String ATTR_CONTENT_ID = "contentId";

    private static final String HTML_HEAD_STRING =
            "<html><head>\n" +
            "<style type=\"text/css\">\n" +
            "body { padding: 0; font-family: sans-serif; }\n" +
            ".same-license { background-color: #eeeeee;\n" +
            "                border-top: 20px solid white;\n" +
            "                padding: 10px; }\n" +
            ".label { font-weight: bold; }\n" +
            ".file-list { margin-left: 1em; color: blue; }\n" +
            "</style>\n" +
            "</head>" +
            "<body topmargin=\"0\" leftmargin=\"0\" rightmargin=\"0\" bottommargin=\"0\">\n" +
            "<div class=\"toc\">\n" +
            "<ul>";

    private static final String HTML_MIDDLE_STRING =
            "</ul>\n" +
            "</div><!-- table of contents -->\n" +
            "<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\">";

    private static final String HTML_REAR_STRING =
            "</table></body></html>";

    private final List<File> mXmlFiles;

    /*
     * A map from a file name to a content id (MD5 sum of file content) for its license.
     * For example, "/system/priv-app/TeleService/TeleService.apk" maps to
     * "9645f39e9db895a4aa6e02cb57294595". Here "9645f39e9db895a4aa6e02cb57294595" is a MD5 sum
     * of the content of packages/services/Telephony/MODULE_LICENSE_APACHE2.
     */
    private final Map<String, String> mFileNameToContentIdMap = new HashMap();

    /*
     * A map from a content id (MD5 sum of file content) to a license file content.
     * For example, "9645f39e9db895a4aa6e02cb57294595" maps to the content string of
     * packages/services/Telephony/MODULE_LICENSE_APACHE2. Here "9645f39e9db895a4aa6e02cb57294595"
     * is a MD5 sum of the file content.
     */
    private final Map<String, String> mContentIdToFileContentMap = new HashMap();

    static class ContentIdAndFileNames {
        final String mContentId;
        final List<String> mFileNameList = new ArrayList();

        ContentIdAndFileNames(String contentId) {
            mContentId = contentId;
        }
    }

    private LicenseHtmlGeneratorFromXml(List<File> xmlFiles) {
        mXmlFiles = xmlFiles;
    }

    public static boolean generateHtml(List<File> xmlFiles, File outputFile) {
        LicenseHtmlGeneratorFromXml genertor = new LicenseHtmlGeneratorFromXml(xmlFiles);
        return genertor.generateHtml(outputFile);
    }

    private boolean generateHtml(File outputFile) {
        for (File xmlFile : mXmlFiles) {
            parse(xmlFile);
        }

        if (mFileNameToContentIdMap.isEmpty() || mContentIdToFileContentMap.isEmpty()) {
            return false;
        }

        PrintWriter writer = null;
        try {
            writer = new PrintWriter(outputFile);

            generateHtml(mFileNameToContentIdMap, mContentIdToFileContentMap, writer);

            writer.flush();
            writer.close();
            return true;
        } catch (FileNotFoundException | SecurityException e) {
            Log.e(TAG, "Failed to generate " + outputFile, e);

            if (writer != null) {
                writer.close();
            }
            return false;
        }
    }

    private void parse(File xmlFile) {
        if (xmlFile == null || !xmlFile.exists() || xmlFile.length() == 0) {
            return;
        }

        InputStreamReader in = null;
        try {
            if (xmlFile.getName().endsWith(".gz")) {
                in = new InputStreamReader(new GZIPInputStream(new FileInputStream(xmlFile)));
            } else {
                in = new FileReader(xmlFile);
            }

            parse(in, mFileNameToContentIdMap, mContentIdToFileContentMap);

            in.close();
        } catch (XmlPullParserException | IOException e) {
            Log.e(TAG, "Failed to parse " + xmlFile, e);
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ie) {
                    Log.w(TAG, "Failed to close " + xmlFile);
                }
            }
        }
    }

    /*
     * Parses an input stream and fills a map from a file name to a content id for its license
     * and a map from a content id to a license file content.
     *
     * Following xml format is expected from the input stream.
     *
     *     <licenses>
     *     <file-name contentId="content_id_of_license1">file1</file-name>
     *     <file-name contentId="content_id_of_license2">file2</file-name>
     *     ...
     *     <file-content contentId="content_id_of_license1">license1 file contents</file-content>
     *     <file-content contentId="content_id_of_license2">license2 file contents</file-content>
     *     ...
     *     </licenses>
     */
    @VisibleForTesting
    static void parse(InputStreamReader in, Map<String, String> outFileNameToContentIdMap,
            Map<String, String> outContentIdToFileContentMap)
                    throws XmlPullParserException, IOException {
        Map<String, String> fileNameToContentIdMap = new HashMap<String, String>();
        Map<String, String> contentIdToFileContentMap = new HashMap<String, String>();

        XmlPullParser parser = Xml.newPullParser();
        parser.setInput(in);
        parser.nextTag();

        parser.require(XmlPullParser.START_TAG, "", TAG_ROOT);

        int state = parser.getEventType();
        while (state != XmlPullParser.END_DOCUMENT) {
            if (state == XmlPullParser.START_TAG) {
                if (TAG_FILE_NAME.equals(parser.getName())) {
                    String contentId = parser.getAttributeValue("", ATTR_CONTENT_ID);
                        if (!TextUtils.isEmpty(contentId)) {
                        String fileName = readText(parser).trim();
                        if (!TextUtils.isEmpty(fileName)) {
                            fileNameToContentIdMap.put(fileName, contentId);
                        }
                    }
                } else if (TAG_FILE_CONTENT.equals(parser.getName())) {
                    String contentId = parser.getAttributeValue("", ATTR_CONTENT_ID);
                    if (!TextUtils.isEmpty(contentId) &&
                            !outContentIdToFileContentMap.containsKey(contentId) &&
                            !contentIdToFileContentMap.containsKey(contentId)) {
                        String fileContent = readText(parser);
                        if (!TextUtils.isEmpty(fileContent)) {
                            contentIdToFileContentMap.put(contentId, fileContent);
                        }
                    }
                }
            }

            state = parser.next();
        }
        outFileNameToContentIdMap.putAll(fileNameToContentIdMap);
        outContentIdToFileContentMap.putAll(contentIdToFileContentMap);
    }

    private static String readText(XmlPullParser parser)
            throws IOException, XmlPullParserException {
        StringBuffer result = new StringBuffer();
        int state = parser.next();
        while (state == XmlPullParser.TEXT) {
            result.append(parser.getText());
            state = parser.next();
        }
        return result.toString();
    }

    @VisibleForTesting
    static void generateHtml(Map<String, String> fileNameToContentIdMap,
            Map<String, String> contentIdToFileContentMap, PrintWriter writer) {
        List<String> fileNameList = new ArrayList();
        fileNameList.addAll(fileNameToContentIdMap.keySet());
        Collections.sort(fileNameList);

        writer.println(HTML_HEAD_STRING);

        int count = 0;
        Map<String, Integer> contentIdToOrderMap = new HashMap();
        List<ContentIdAndFileNames> contentIdAndFileNamesList = new ArrayList();

        // Prints all the file list with a link to its license file content.
        for (String fileName : fileNameList) {
            String contentId = fileNameToContentIdMap.get(fileName);
            // Assigns an id to a newly referred license file content.
            if (!contentIdToOrderMap.containsKey(contentId)) {
                contentIdToOrderMap.put(contentId, count);

                // An index in contentIdAndFileNamesList is the order of each element.
                contentIdAndFileNamesList.add(new ContentIdAndFileNames(contentId));
                count++;
            }

            int id = contentIdToOrderMap.get(contentId);
            contentIdAndFileNamesList.get(id).mFileNameList.add(fileName);
            writer.format("<li><a href=\"#id%d\">%s</a></li>\n", id, fileName);
        }

        writer.println(HTML_MIDDLE_STRING);

        count = 0;
        // Prints all contents of the license files in order of id.
        for (ContentIdAndFileNames contentIdAndFileNames : contentIdAndFileNamesList) {
            writer.format("<tr id=\"id%d\"><td class=\"same-license\">\n", count);
            writer.println("<div class=\"label\">Notices for file(s):</div>");
            writer.println("<div class=\"file-list\">");
            for (String fileName : contentIdAndFileNames.mFileNameList) {
                writer.format("%s <br/>\n", fileName);
            }
            writer.println("</div><!-- file-list -->");
            writer.println("<pre class=\"license-text\">");
            writer.println(contentIdToFileContentMap.get(
                    contentIdAndFileNames.mContentId));
            writer.println("</pre><!-- license-text -->");
            writer.println("</td></tr><!-- same-license -->");

            count++;
        }

        writer.println(HTML_REAR_STRING);
    }
}
+110 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * 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.android.settings;

import android.content.Context;
import android.support.annotation.VisibleForTesting;
import android.util.Log;

import com.android.settings.utils.AsyncLoader;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * LicenseHtmlLoader is a loader which loads a license html file from default license xml files.
 */
class LicenseHtmlLoader extends AsyncLoader<File> {
    private static final String TAG = "LicenseHtmlLoader";

    private static final String[] DEFAULT_LICENSE_XML_PATHS = {
                "/system/etc/NOTICE.xml.gz",
                "/vendor/etc/NOTICE.xml.gz",
                "/odm/etc/NOTICE.xml.gz",
                "/oem/etc/NOTICE.xml.gz"};
    private static final String NOTICE_HTML_FILE_NAME = "NOTICE.html";

    private Context mContext;

    public LicenseHtmlLoader(Context context) {
        super(context);
        mContext = context;
    }

    @Override
    public File loadInBackground() {
        return generateHtmlFromDefaultXmlFiles();
    }

    @Override
    protected void onDiscardResult(File f) {
    }

    private File generateHtmlFromDefaultXmlFiles() {
        final List<File> xmlFiles = getVaildXmlFiles();
        if (xmlFiles.isEmpty()) {
            Log.e(TAG, "No notice file exists.");
            return null;
        }

        File cachedHtmlFile = getCachedHtmlFile();
        if(!isCachedHtmlFileOutdated(xmlFiles, cachedHtmlFile) ||
                generateHtmlFile(xmlFiles, cachedHtmlFile)) {
            return cachedHtmlFile;
        }

        return null;
    }

    @VisibleForTesting
    List<File> getVaildXmlFiles() {
        final List<File> xmlFiles = new ArrayList();
        for (final String xmlPath : DEFAULT_LICENSE_XML_PATHS) {
            File file = new File(xmlPath);
            if (file.exists() && file.length() != 0) {
                xmlFiles.add(file);
            }
        }
        return xmlFiles;
    }

    @VisibleForTesting
    File getCachedHtmlFile() {
        return new File(mContext.getCacheDir(), NOTICE_HTML_FILE_NAME);
    }

    @VisibleForTesting
    boolean isCachedHtmlFileOutdated(List<File> xmlFiles, File cachedHtmlFile) {
        boolean outdated = true;
        if (cachedHtmlFile.exists() && cachedHtmlFile.length() != 0) {
            outdated = false;
            for (File file : xmlFiles) {
                if (cachedHtmlFile.lastModified() < file.lastModified()) {
                    outdated = true;
                    break;
                }
            }
        }
        return outdated;
    }

    @VisibleForTesting
    boolean generateHtmlFile(List<File> xmlFiles, File htmlFile) {
        return LicenseHtmlGeneratorFromXml.generateHtml(xmlFiles, htmlFile);
    }
}
+74 −4
Original line number Original line Diff line number Diff line
@@ -17,32 +17,87 @@
package com.android.settings;
package com.android.settings;


import android.app.Activity;
import android.app.Activity;
import android.app.LoaderManager;
import android.content.ActivityNotFoundException;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.Loader;
import android.net.Uri;
import android.net.Uri;
import android.os.Bundle;
import android.os.Bundle;
import android.os.StrictMode;
import android.os.StrictMode;
import android.os.SystemProperties;
import android.os.SystemProperties;
import android.support.annotation.VisibleForTesting;
import android.support.v4.content.FileProvider;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.Log;
import android.util.Log;
import android.widget.Toast;
import android.widget.Toast;


import com.android.settings.users.RestrictedProfileSettings;

import java.io.File;
import java.io.File;
import java.util.ArrayList;
import java.util.List;


/**
/**
 * The "dialog" that shows from "License" in the Settings app.
 * The "dialog" that shows from "License" in the Settings app.
 */
 */
public class SettingsLicenseActivity extends Activity {
public class SettingsLicenseActivity extends Activity implements
            LoaderManager.LoaderCallbacks<File> {
    private static final String TAG = "SettingsLicenseActivity";
    private static final String TAG = "SettingsLicenseActivity";


    private static final String DEFAULT_LICENSE_PATH = "/system/etc/NOTICE.html.gz";
    private static final String DEFAULT_LICENSE_PATH = "/system/etc/NOTICE.html.gz";
    private static final String PROPERTY_LICENSE_PATH = "ro.config.license_path";
    private static final String PROPERTY_LICENSE_PATH = "ro.config.license_path";


    private static final int LOADER_ID_LICENSE_HTML_LOADER = 0;

    @Override
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.onCreate(savedInstanceState);


        final String path = SystemProperties.get(PROPERTY_LICENSE_PATH, DEFAULT_LICENSE_PATH);
        final String licenseHtmlPath =
                SystemProperties.get(PROPERTY_LICENSE_PATH, DEFAULT_LICENSE_PATH);
        if (isFilePathValid(licenseHtmlPath)) {
            showSelectedFile(licenseHtmlPath);
        } else {
            showHtmlFromDefaultXmlFiles();
        }
    }

    @Override
    public Loader<File> onCreateLoader(int id, Bundle args) {
        return new LicenseHtmlLoader(this);
    }

    @Override
    public void onLoadFinished(Loader<File> loader, File generatedHtmlFile) {
        showGeneratedHtmlFile(generatedHtmlFile);
    }

    @Override
    public void onLoaderReset(Loader<File> loader) {
    }

    private void showHtmlFromDefaultXmlFiles() {
        getLoaderManager().initLoader(LOADER_ID_LICENSE_HTML_LOADER, Bundle.EMPTY, this);
    }

    @VisibleForTesting
    Uri getUriFromGeneratedHtmlFile(File generatedHtmlFile) {
        return FileProvider.getUriForFile(this, RestrictedProfileSettings.FILE_PROVIDER_AUTHORITY,
                generatedHtmlFile);
    }

    private void showGeneratedHtmlFile(File generatedHtmlFile) {
        if (generatedHtmlFile != null) {
            showHtmlFromUri(getUriFromGeneratedHtmlFile(generatedHtmlFile));
        } else {
            Log.e(TAG, "Failed to generate.");
            showErrorAndFinish();
        }
    }

    private void showSelectedFile(final String path) {
        if (TextUtils.isEmpty(path)) {
        if (TextUtils.isEmpty(path)) {
            Log.e(TAG, "The system property for the license file is empty");
            Log.e(TAG, "The system property for the license file is empty");
            showErrorAndFinish();
            showErrorAndFinish();
@@ -50,18 +105,24 @@ public class SettingsLicenseActivity extends Activity {
        }
        }


        final File file = new File(path);
        final File file = new File(path);
        if (!file.exists() || file.length() == 0) {
        if (!isFileValid(file)) {
            Log.e(TAG, "License file " + path + " does not exist");
            Log.e(TAG, "License file " + path + " does not exist");
            showErrorAndFinish();
            showErrorAndFinish();
            return;
            return;
        }
        }
        showHtmlFromUri(Uri.fromFile(file));
     }


     private void showHtmlFromUri(Uri uri) {
        // Kick off external viewer due to WebView security restrictions; we
        // Kick off external viewer due to WebView security restrictions; we
        // carefully point it at HTMLViewer, since it offers to decompress
        // carefully point it at HTMLViewer, since it offers to decompress
        // before viewing.
        // before viewing.
        final Intent intent = new Intent(Intent.ACTION_VIEW);
        final Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.fromFile(file), "text/html");
        intent.setDataAndType(uri, "text/html");
        intent.putExtra(Intent.EXTRA_TITLE, getString(R.string.settings_license_activity_title));
        intent.putExtra(Intent.EXTRA_TITLE, getString(R.string.settings_license_activity_title));
        if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        intent.setPackage("com.android.htmlviewer");
        intent.setPackage("com.android.htmlviewer");


@@ -79,4 +140,13 @@ public class SettingsLicenseActivity extends Activity {
                .show();
                .show();
        finish();
        finish();
    }
    }

    private boolean isFilePathValid(final String path) {
        return !TextUtils.isEmpty(path) && isFileValid(new File(path));
    }

    @VisibleForTesting
    boolean isFileValid(final File file) {
        return file.exists() && file.length() != 0;
    }
}
}
+123 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * 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.android.settings;

import static com.google.common.truth.Truth.assertThat;

import java.util.HashMap;
import java.util.Map;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;
import org.xmlpull.v1.XmlPullParserException;

@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class LicenseHtmlGeneratorFromXmlTest {
    private static final String VAILD_XML_STRING =
            "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
            "<licenses>\n" +
            "<file-name contentId=\"0\">/file0</file-name>\n" +
            "<file-name contentId=\"0\">/file1</file-name>\n" +
            "<file-content contentId=\"0\"><![CDATA[license content #0]]></file-content>\n" +
            "</licenses>";

    private static final String INVAILD_XML_STRING =
            "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
            "<licenses2>\n" +
            "<file-name contentId=\"0\">/file0</file-name>\n" +
            "<file-name contentId=\"0\">/file1</file-name>\n" +
            "<file-content contentId=\"0\"><![CDATA[license content #0]]></file-content>\n" +
            "</licenses2>";

    private static final String EXPECTED_HTML_STRING =
            "<html><head>\n" +
            "<style type=\"text/css\">\n" +
            "body { padding: 0; font-family: sans-serif; }\n" +
            ".same-license { background-color: #eeeeee;\n" +
            "                border-top: 20px solid white;\n" +
            "                padding: 10px; }\n" +
            ".label { font-weight: bold; }\n" +
            ".file-list { margin-left: 1em; color: blue; }\n" +
            "</style>\n" +
            "</head>" +
            "<body topmargin=\"0\" leftmargin=\"0\" rightmargin=\"0\" bottommargin=\"0\">\n" +
            "<div class=\"toc\">\n" +
            "<ul>\n" +
            "<li><a href=\"#id0\">/file0</a></li>\n" +
            "<li><a href=\"#id0\">/file1</a></li>\n" +
            "</ul>\n" +
            "</div><!-- table of contents -->\n" +
            "<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n" +
            "<tr id=\"id0\"><td class=\"same-license\">\n" +
            "<div class=\"label\">Notices for file(s):</div>\n" +
            "<div class=\"file-list\">\n" +
            "/file0 <br/>\n" +
            "/file1 <br/>\n" +
            "</div><!-- file-list -->\n" +
            "<pre class=\"license-text\">\n" +
            "license content #0\n" +
            "</pre><!-- license-text -->\n" +
            "</td></tr><!-- same-license -->\n" +
            "</table></body></html>\n";

    @Test
    public void testParseValidXmlStream() throws XmlPullParserException, IOException {
        Map<String, String> fileNameToContentIdMap = new HashMap<String, String>();
        Map<String, String> contentIdToFileContentMap = new HashMap<String, String>();

        LicenseHtmlGeneratorFromXml.parse(
                new InputStreamReader(new ByteArrayInputStream(VAILD_XML_STRING.getBytes())),
                fileNameToContentIdMap, contentIdToFileContentMap);
        assertThat(fileNameToContentIdMap.size()).isEqualTo(2);
        assertThat(fileNameToContentIdMap.get("/file0")).isEqualTo("0");
        assertThat(fileNameToContentIdMap.get("/file1")).isEqualTo("0");
        assertThat(contentIdToFileContentMap.size()).isEqualTo(1);
        assertThat(contentIdToFileContentMap.get("0")).isEqualTo("license content #0");
    }

    @Test(expected = XmlPullParserException.class)
    public void testParseInvalidXmlStream() throws XmlPullParserException, IOException {
        Map<String, String> fileNameToContentIdMap = new HashMap<String, String>();
        Map<String, String> contentIdToFileContentMap = new HashMap<String, String>();

        LicenseHtmlGeneratorFromXml.parse(
                new InputStreamReader(new ByteArrayInputStream(INVAILD_XML_STRING.getBytes())),
                fileNameToContentIdMap, contentIdToFileContentMap);
    }

    @Test
    public void testGenerateHtml() {
        Map<String, String> fileNameToContentIdMap = new HashMap<String, String>();
        Map<String, String> contentIdToFileContentMap = new HashMap<String, String>();

        fileNameToContentIdMap.put("/file0", "0");
        fileNameToContentIdMap.put("/file1", "0");
        contentIdToFileContentMap.put("0", "license content #0");

        StringWriter output = new StringWriter();
        LicenseHtmlGeneratorFromXml.generateHtml(
                fileNameToContentIdMap, contentIdToFileContentMap, new PrintWriter(output));
        assertThat(output.toString()).isEqualTo(EXPECTED_HTML_STRING);
    }
}
+109 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading