From c96e2cc6efaf5d5c0a789be72bc6375b3cb47b86 Mon Sep 17 00:00:00 2001 From: "Svetlana.Zemlyanskaya" Date: Mon, 4 Feb 2019 16:35:30 +0100 Subject: [PATCH] FUS: add action to test whitelist --- .../TestParseEventLogWhitelistAction.java | 34 +++ .../TestParseEventLogWhitelistDialog.form | 83 +++++++ .../TestParseEventLogWhitelistDialog.java | 184 ++++++++++++++ .../FeatureStatisticsWhitelistTest.kt | 224 ++++++++++++++++++ resources/src/idea/RichPlatformActions.xml | 5 + 5 files changed, 530 insertions(+) create mode 100644 platform/lang-impl/src/com/intellij/internal/statistic/actions/TestParseEventLogWhitelistAction.java create mode 100644 platform/lang-impl/src/com/intellij/internal/statistic/actions/TestParseEventLogWhitelistDialog.form create mode 100644 platform/lang-impl/src/com/intellij/internal/statistic/actions/TestParseEventLogWhitelistDialog.java diff --git a/platform/lang-impl/src/com/intellij/internal/statistic/actions/TestParseEventLogWhitelistAction.java b/platform/lang-impl/src/com/intellij/internal/statistic/actions/TestParseEventLogWhitelistAction.java new file mode 100644 index 000000000000..04cd1dc05285 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/internal/statistic/actions/TestParseEventLogWhitelistAction.java @@ -0,0 +1,34 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.internal.statistic.actions; + +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.application.ex.ApplicationManagerEx; +import com.intellij.openapi.project.DumbAwareAction; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class TestParseEventLogWhitelistAction extends DumbAwareAction { + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + final Project project = e.getProject(); + if (project != null) { + new TestParseEventLogWhitelistDialog(project, e.getData(CommonDataKeys.EDITOR)).show(); + } + } + + @Override + public void update(@NotNull AnActionEvent e) { + boolean enabled = isEnabled(e.getProject()); + e.getPresentation().setEnabledAndVisible(enabled); + if (enabled && e.getData(CommonDataKeys.EDITOR) == null) { + e.getPresentation().setEnabled(false); + } + } + + private static boolean isEnabled(@Nullable Project project) { + return project != null && ApplicationManagerEx.getApplicationEx().isInternal(); + } +} \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/internal/statistic/actions/TestParseEventLogWhitelistDialog.form b/platform/lang-impl/src/com/intellij/internal/statistic/actions/TestParseEventLogWhitelistDialog.form new file mode 100644 index 000000000000..76fc305af526 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/internal/statistic/actions/TestParseEventLogWhitelistDialog.form @@ -0,0 +1,83 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/platform/lang-impl/src/com/intellij/internal/statistic/actions/TestParseEventLogWhitelistDialog.java b/platform/lang-impl/src/com/intellij/internal/statistic/actions/TestParseEventLogWhitelistDialog.java new file mode 100644 index 000000000000..7503708172ea --- /dev/null +++ b/platform/lang-impl/src/com/intellij/internal/statistic/actions/TestParseEventLogWhitelistDialog.java @@ -0,0 +1,184 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.internal.statistic.actions; + +import com.intellij.internal.statistic.eventLog.*; +import com.intellij.internal.statistic.service.fus.FUStatisticsWhiteListGroupsService; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.editor.ScrollType; +import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.editor.highlighter.EditorHighlighter; +import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.BuildNumber; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.testFramework.LightVirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.io.File; +import java.io.IOException; +import java.util.Set; + +public class TestParseEventLogWhitelistDialog extends DialogWrapper { + private static final Logger LOG = Logger.getInstance(TestParseEventLogWhitelistDialog.class); + + private static final int IN_DIVIDER_LOCATION = 650; + private static final int IN_OUT_DIVIDER_LOCATION = 500; + private JPanel myMainPanel; + private JPanel myWhitelistPanel; + private JEditorPane myEventLogPanel; + private JSplitPane myInputDataSplitPane; + private JSplitPane myInputOutputSplitPane; + private JEditorPane myResultPane; + + private final Project myProject; + private final EditorEx myEditor; + + protected TestParseEventLogWhitelistDialog(@NotNull Project project, @Nullable Editor selectedEditor) { + super(project); + myProject = project; + setOKButtonText("&Filter Event Log"); + setCancelButtonText("&Close"); + Disposer.register(myProject, getDisposable()); + VirtualFile selectedFile = selectedEditor == null ? null : FileDocumentManager.getInstance().getFile(selectedEditor.getDocument()); + setTitle(selectedFile == null ? "Event Log Filter" : "Event Log Filter by: " + selectedFile.getName()); + myEditor = initEditor(selectedEditor); + myEditor.getSettings().setLineMarkerAreaShown(false); + + init(); + if (selectedEditor != null) { + doOKAction(); + + ApplicationManager.getApplication().invokeLater(() -> { + IdeFocusManager.getGlobalInstance() + .doWhenFocusSettlesDown(() -> IdeFocusManager.getGlobalInstance().requestFocus(myEditor.getContentComponent(), true)); + myEditor.getCaretModel().moveToOffset(selectedEditor.getCaretModel().getOffset()); + myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); + }, ModalityState.stateForComponent(myMainPanel)); + } + } + + @NotNull + private EditorEx initEditor(@Nullable Editor selectedEditor) { + if (selectedEditor != null) { + return (EditorEx)EditorFactory.getInstance().createEditor(selectedEditor.getDocument(), myProject); + } + else { + Document document = EditorFactory.getInstance().createDocument(StringUtil.notNullize("{}")); + EditorEx editor = (EditorEx)EditorFactory.getInstance().createEditor(document, myProject); + editor.getSelectionModel().setSelection(0, document.getTextLength()); + return editor; + } + } + + @Override + protected void init() { + configEditorPanel(myProject, myWhitelistPanel, myEditor); + + myInputDataSplitPane.setDividerLocation(IN_DIVIDER_LOCATION); + myInputOutputSplitPane.setDividerLocation(IN_OUT_DIVIDER_LOCATION); + super.init(); + } + + private static void configEditorPanel(@NotNull Project project, @NotNull JPanel panel, @NotNull EditorEx editor) { + panel.setLayout(new BorderLayout()); + panel.add(editor.getComponent(), BorderLayout.CENTER); + + editor.getSettings().setFoldingOutlineShown(false); + final FileType fileType = FileTypeManager.getInstance().findFileTypeByName("JSON"); + final LightVirtualFile lightFile = new LightVirtualFile("Dummy.json", fileType, ""); + + EditorHighlighter highlighter = EditorHighlighterFactory.getInstance().createEditorHighlighter(project, lightFile); + try { + editor.setHighlighter(highlighter); + } + catch (Throwable e) { + LOG.warn(e); + } + } + + @Override + @NotNull + protected String getDimensionServiceKey() { + return TestParseEventLogWhitelistDialog.class.getCanonicalName(); + } + + @SuppressWarnings("TestOnlyProblems") + @Override + protected void doOKAction() { + myEditor.getSelectionModel().removeSelection(); + updateOutputText(""); + + final BuildNumber build = BuildNumber.fromString(EventLogConfiguration.INSTANCE.getBuild()); + final Set groups = FUStatisticsWhiteListGroupsService.parseApprovedGroups(myEditor.getDocument().getText(), build); + try { + final String parsed = parseLogAndFilter(new LogEventWhitelistFilter(groups), myEventLogPanel.getText()); + updateOutputText(parsed.trim()); + } + catch (IOException | ParseEventLogWhitelistException e) { + Messages.showErrorDialog(myProject, e.getMessage(), "Failed Applying Whitelist to Event Log"); + } + } + + private void updateOutputText(@NotNull String text) { + myResultPane.setText(text); + } + + @NotNull + private static String parseLogAndFilter(@NotNull LogEventFilter filter, @NotNull String text) + throws IOException, ParseEventLogWhitelistException { + final File log = FileUtil.createTempFile("feature-event-log", ".log"); + try { + FileUtil.writeToFile(log, text); + final LogEventRecordRequest request = LogEventRecordRequest.Companion.create(log, filter, true); + if (request == null) { + throw new ParseEventLogWhitelistException("Failed parsing event log"); + } + return LogEventSerializer.INSTANCE.toString(request); + } + finally { + FileUtil.delete(log); + } + } + + @Nullable + @Override + protected JComponent createCenterPanel() { + return myMainPanel; + } + + @Override + public JComponent getPreferredFocusedComponent() { + return myEventLogPanel; + } + + @Override + public void dispose() { + if (!myEditor.isDisposed()) { + EditorFactory.getInstance().releaseEditor(myEditor); + } + super.dispose(); + } + + public static class ParseEventLogWhitelistException extends Exception { + public ParseEventLogWhitelistException(String s) { + super(s); + } + } +} diff --git a/platform/platform-tests/testSrc/com/intellij/internal/statistics/FeatureStatisticsWhitelistTest.kt b/platform/platform-tests/testSrc/com/intellij/internal/statistics/FeatureStatisticsWhitelistTest.kt index 3fb114def4a5..a8799b3e3732 100644 --- a/platform/platform-tests/testSrc/com/intellij/internal/statistics/FeatureStatisticsWhitelistTest.kt +++ b/platform/platform-tests/testSrc/com/intellij/internal/statistics/FeatureStatisticsWhitelistTest.kt @@ -672,6 +672,230 @@ class FeatureStatisticsWhitelistTest { doTest(content, "183.2495", "test.group.id") } + @Test + fun `with from snapshot and build later is accepted`() { + val content = """ +{ + "groups" : [{ + "id" : "test.group.id", + "title" : "Test Group", + "description" : "Test group description", + "type" : "counter", + "builds" : [ { + "from" : "183.0" + }], + "context" : { + } + }] +} + """ + doTest(content, "183.1495", "test.group.id") + } + + @Test + fun `with from snapshot and build later with bugfix update is accepted`() { + val content = """ +{ + "groups" : [{ + "id" : "test.group.id", + "title" : "Test Group", + "description" : "Test group description", + "type" : "counter", + "builds" : [ { + "from" : "183.0" + }], + "context" : { + } + }] +} + """ + doTest(content, "183.1495.245", "test.group.id") + } + + @Test + fun `with from snapshot and build earlier is not accepted`() { + val content = """ +{ + "groups" : [{ + "id" : "test.group.id", + "title" : "Test Group", + "description" : "Test group description", + "type" : "counter", + "builds" : [ { + "from" : "191.0" + }], + "context" : { + } + }] +} + """ + doTest(content, "183.1495") + } + + @Test + fun `with from equals to build is accepted`() { + val content = """ +{ + "groups" : [{ + "id" : "test.group.id", + "title" : "Test Group", + "description" : "Test group description", + "type" : "counter", + "builds" : [ { + "from" : "183.1495" + }], + "context" : { + } + }] +} + """ + doTest(content, "183.1495", "test.group.id") + } + + @Test + fun `with from middle number equals to build is accepted`() { + val content = """ +{ + "groups" : [{ + "id" : "test.group.id", + "title" : "Test Group", + "description" : "Test group description", + "type" : "counter", + "builds" : [ { + "from" : "183.1495" + }], + "context" : { + } + }] +} + """ + doTest(content, "183.1495.0", "test.group.id") + } + + @Test + fun `with from middle number equals to build and last is bigger is accepted`() { + val content = """ +{ + "groups" : [{ + "id" : "test.group.id", + "title" : "Test Group", + "description" : "Test group description", + "type" : "counter", + "builds" : [ { + "from" : "183.1495" + }], + "context" : { + } + }] +} + """ + doTest(content, "183.1495.12", "test.group.id") + } + + @Test + fun `with build middle number equals to from and last is bigger is not accepted`() { + val content = """ +{ + "groups" : [{ + "id" : "test.group.id", + "title" : "Test Group", + "description" : "Test group description", + "type" : "counter", + "builds" : [ { + "from" : "183.1495.12" + }], + "context" : { + } + }] +} + """ + doTest(content, "183.1495") + } + + @Test + fun `with build middle number equals to to is not accepted`() { + val content = """ +{ + "groups" : [{ + "id" : "test.group.id", + "title" : "Test Group", + "description" : "Test group description", + "type" : "counter", + "builds" : [ { + "from" : "183.1495.12", + "to": "183.4885" + }], + "context" : { + } + }] +} + """ + doTest(content, "183.4885") + } + + @Test + fun `with build middle number equals to to and last is bigger is not accepted`() { + val content = """ +{ + "groups" : [{ + "id" : "test.group.id", + "title" : "Test Group", + "description" : "Test group description", + "type" : "counter", + "builds" : [ { + "from" : "183.1495.12", + "to": "183.4885" + }], + "context" : { + } + }] +} + """ + doTest(content, "183.4885.35") + } + + @Test + fun `with build middle number smaller then to is accepted`() { + val content = """ +{ + "groups" : [{ + "id" : "test.group.id", + "title" : "Test Group", + "description" : "Test group description", + "type" : "counter", + "builds" : [ { + "from" : "183.1495.12", + "to": "183.4885" + }], + "context" : { + } + }] +} + """ + doTest(content, "183.4884.35", "test.group.id") + } + + @Test + fun `with build middle number smaller then to and have two numbers is accepted`() { + val content = """ +{ + "groups" : [{ + "id" : "test.group.id", + "title" : "Test Group", + "description" : "Test group description", + "type" : "counter", + "builds" : [ { + "from" : "183.1495.12", + "to": "183.4885" + }], + "context" : { + } + }] +} + """ + doTest(content, "183.4884", "test.group.id") + } + @Test fun `snapshot builds major greater than from is accepted`() { val content = """ diff --git a/resources/src/idea/RichPlatformActions.xml b/resources/src/idea/RichPlatformActions.xml index 5bff857de91c..d350b3c18185 100644 --- a/resources/src/idea/RichPlatformActions.xml +++ b/resources/src/idea/RichPlatformActions.xml @@ -172,6 +172,11 @@ + + + +