diff --git a/frontend/client/src/autotest/tko/TestDetailView.java b/frontend/client/src/autotest/tko/TestDetailView.java
index 30337e8..9f32a0a 100644
--- a/frontend/client/src/autotest/tko/TestDetailView.java
+++ b/frontend/client/src/autotest/tko/TestDetailView.java
@@ -7,11 +7,13 @@ import autotest.common.Utils;
 import autotest.common.ui.DetailView;
 import autotest.common.ui.NotifyManager;
 import autotest.common.ui.RealHyperlink;
+import autotest.common.StaticDataRepository;
 
 import com.google.gwt.json.client.JSONNumber;
 import com.google.gwt.json.client.JSONObject;
 import com.google.gwt.json.client.JSONString;
 import com.google.gwt.json.client.JSONValue;
+import com.google.gwt.json.client.JSONArray;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.WindowResizeListener;
 import com.google.gwt.user.client.ui.Composite;
@@ -24,6 +26,11 @@ import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.Panel;
 import com.google.gwt.user.client.ui.RootPanel;
 import com.google.gwt.user.client.ui.ScrollPanel;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.Widget;
+
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -33,17 +40,22 @@ import java.util.List;
 class TestDetailView extends DetailView {
     private static final int NO_TEST_ID = -1;
 
-    private static final JsonRpcProxy logLoadingProxy = 
+    private static final JsonRpcProxy logLoadingProxy =
         new PaddedJsonRpcProxy(Utils.RETRIEVE_LOGS_URL);
 
+    private static JsonRpcProxy rpcProxy = JsonRpcProxy.getProxy();
     private int testId = NO_TEST_ID;
+    private String testName = null;
     private String jobTag;
     private List<LogFileViewer> logFileViewers = new ArrayList<LogFileViewer>();
-    private RealHyperlink logLink = new RealHyperlink("(view all logs)");
 
+    private RealHyperlink logLink = new RealHyperlink("(view all logs)");
+    protected static TextBox attrInput = new TextBox();
+    protected static TextBox testSetInput = new TextBox();
+    protected Button attrUpdateButton = new Button("Save");
     private Panel logPanel;
-    
-    private class LogFileViewer extends Composite 
+
+    private class LogFileViewer extends Composite
                                 implements DisclosureHandler, WindowResizeListener {
         private DisclosurePanel panel;
         private ScrollPanel scroller; // ScrollPanel wrapping log contents
@@ -65,17 +77,17 @@ class TestDetailView extends DetailView {
                 handle(result);
             }
         };
-        
+
         public LogFileViewer(String logFilePath, String logFileName) {
             this.logFilePath = logFilePath;
             panel = new DisclosurePanel(logFileName);
             panel.addEventHandler(this);
             panel.addStyleName("log-file-panel");
             initWidget(panel);
-            
+
             Window.addWindowResizeListener(this);
         }
-        
+
         public void onOpen(DisclosureEvent event) {
             JSONObject params = new JSONObject();
             params.put("path", new JSONString(getLogUrl()));
@@ -87,7 +99,7 @@ class TestDetailView extends DetailView {
         private String getLogUrl() {
             return Utils.getLogsUrl(jobTag + "/" + logFilePath);
         }
-        
+
         public void handle(JSONValue value) {
             String logContents = value.isString().stringValue();
             if (logContents.equals("")) {
@@ -106,8 +118,8 @@ class TestDetailView extends DetailView {
         }
 
         /**
-         * Firefox fails to set relative widths correctly for elements with overflow: scroll (or 
-         * auto, or hidden).  Instead, it just expands the element to fit the contents.  So we use 
+         * Firefox fails to set relative widths correctly for elements with overflow: scroll (or
+         * auto, or hidden).  Instead, it just expands the element to fit the contents.  So we use
          * this trick to dynamically implement width: 100%.
          */
         private void setScrollerWidth() {
@@ -131,11 +143,119 @@ class TestDetailView extends DetailView {
 
         public void onClose(DisclosureEvent event) {}
     }
-    
+
+
+    /* This class handles the test comparison analysis.*/
+    private static class AnalysisTable extends Composite implements DisclosureHandler {
+        private ScrollPanel scroller;
+        private int testID;
+        private DisclosurePanel panel = new DisclosurePanel("Test case comparison");
+        private JsonRpcCallback rpcCallback = new JsonRpcCallback() {
+            @Override
+            public void onError(JSONObject errorObject) {
+                super.onError(errorObject);
+                String errorString = getErrorString(errorObject);
+                if (errorString.equals("")) {
+                    errorString = "No comparison analysis data available for this configuration.";
+                }
+                setStatusText(errorString);
+            }
+
+            @Override
+            public void onSuccess(JSONValue result) {
+                handle(result);
+            }
+
+        };
+
+        public AnalysisTable(int tid) {
+            this.testID = tid;
+            panel.addEventHandler(this);
+            panel.addStyleName("test-analysis");
+            initWidget(panel);
+        }
+
+        public void onOpen(DisclosureEvent event) {
+            JSONObject params = new JSONObject();
+            params.put("test", new JSONString(Integer.toString(testID)));
+            params.put("attr", new JSONString(attrInput.getText()));
+            params.put("testset", new JSONString(testSetInput.getText()));
+            rpcProxy.rpcCall("get_testcase_comparison_data", params, rpcCallback);
+            setStatusText("Loading (may take few seconds)...");
+        }
+
+        public void handle(JSONValue value) {
+            String contents = value.isString().stringValue();
+            if (contents.equals("")) {
+                setText("No analysis data for this test case.");
+            } else {
+                setText(contents);
+            }
+        }
+
+        private void setText(String text) {
+            panel.clear();
+            scroller = new ScrollPanel();
+            scroller.getElement().setInnerText(text);
+            panel.add(scroller);
+        }
+
+        private void setStatusText(String status) {
+            panel.clear();
+            panel.add(new HTML("<i>" + status + "</i>"));
+        }
+
+        public void onClose(DisclosureEvent event) {}
+
+    }
+
+
+    private void retrieveComparisonAttributes(String testName) {
+        attrInput.setText("");
+        testSetInput.setText("");
+        StaticDataRepository staticData = StaticDataRepository.getRepository();
+        JSONObject args = new JSONObject();
+        args.put("owner", new JSONString(staticData.getCurrentUserLogin()));
+        args.put("testname", new JSONString(testName));
+
+        rpcProxy.rpcCall("get_test_comparison_attr", args, new JsonRpcCallback() {
+            @Override
+            public void onSuccess(JSONValue result) {
+                JSONArray queries = result.isArray();
+                if (queries.size() == 0) {
+                    return;
+                }
+                assert queries.size() == 1;
+                JSONObject query = queries.get(0).isObject();
+                attrInput.setText(query.get("attributes").isString().stringValue());
+                testSetInput.setText(query.get("testset").isString().stringValue());
+                return;
+            }
+        });
+
+    }
+
+    public void saveComparisonAttribute() {
+        StaticDataRepository staticData = StaticDataRepository.getRepository();
+        JSONObject args = new JSONObject();
+        args.put("name", new JSONString(testName));
+        args.put("owner", new JSONString(staticData.getCurrentUserLogin()));
+        args.put("attr_token", new JSONString(attrInput.getText()));
+        args.put("testset_token", new JSONString(testSetInput.getText()));
+        rpcProxy.rpcCall("add_test_comparison_attr", args, new JsonRpcCallback() {
+           @Override
+           public void onSuccess(JSONValue result) {
+              NotifyManager.getInstance().showMessage("Test comparison attributes saved");
+           }
+        });
+   }
+
+
+
     private static class AttributeTable extends Composite {
         private DisclosurePanel container = new DisclosurePanel("Test attributes");
         private FlexTable table = new FlexTable();
-        
+
         public AttributeTable(JSONObject attributes) {
             processAttributes(attributes);
             setupTableStyle();
@@ -148,7 +268,7 @@ class TestDetailView extends DetailView {
                 table.setText(0, 0, "No test attributes");
                 return;
             }
-            
+
             List<String> sortedKeys = new ArrayList<String>(attributes.keySet());
             Collections.sort(sortedKeys);
             for (String key : sortedKeys) {
@@ -158,7 +278,7 @@ class TestDetailView extends DetailView {
                 table.setText(row, 1, value);
             }
         }
-        
+
         private void setupTableStyle() {
             container.addStyleName("test-attributes");
         }
@@ -167,12 +287,21 @@ class TestDetailView extends DetailView {
     @Override
     public void initialize() {
         super.initialize();
-        
+        RootPanel.get(getTdCompAttrControlId()).add(attrInput);
+        RootPanel.get(getTdCompSetNameControlId()).add(testSetInput);
+        RootPanel.get(getTdCompSaveControlId()).add(attrUpdateButton);
+
         logPanel = new FlowPanel();
         RootPanel.get("td_log_files").add(logPanel);
-        
+
         logLink.setOpensNewWindow(true);
         RootPanel.get("td_view_logs_link").add(logLink);
+
+        attrUpdateButton.addClickListener(new ClickListener() {
+            public void onClick(Widget sender) {
+                saveComparisonAttribute();
+            }
+        });
     }
 
     private void addLogViewers(String testName) {
@@ -206,10 +335,10 @@ class TestDetailView extends DetailView {
                     resetPage();
                     return;
                 }
-                
+                testName = new String(test.get("test_name").isString().stringValue());
                 showTest(test);
             }
-            
+
             @Override
             public void onError(JSONObject errorObject) {
                 super.onError(errorObject);
@@ -217,7 +346,7 @@ class TestDetailView extends DetailView {
             }
         });
     }
-    
+
     @Override
     protected void setObjectId(String id) {
         try {
@@ -227,7 +356,7 @@ class TestDetailView extends DetailView {
             throw new IllegalArgumentException();
         }
     }
-    
+
     @Override
     protected String getObjectId() {
         if (testId == NO_TEST_ID) {
@@ -260,7 +389,19 @@ class TestDetailView extends DetailView {
     public String getElementId() {
         return "test_detail_view";
     }
-    
+
+    protected String getTdCompAttrControlId() {
+        return "td_comp_attr_control";
+    }
+
+    protected String getTdCompSetNameControlId() {
+        return "td_comp_name_control";
+    }
+
+    protected String getTdCompSaveControlId() {
+        return "td_comp_save_control";
+    }
+
     @Override
     public void display() {
         super.display();
@@ -270,7 +411,8 @@ class TestDetailView extends DetailView {
     protected void showTest(JSONObject test) {
         String testName = test.get("test_name").isString().stringValue();
         jobTag = test.get("job_tag").isString().stringValue();
-        
+
+        retrieveComparisonAttributes(testName);
         showText(testName, "td_test");
         showText(jobTag, "td_job_tag");
         showField(test, "job_name", "td_job_name");
@@ -281,22 +423,22 @@ class TestDetailView extends DetailView {
         showField(test, "hostname", "td_hostname");
         showField(test, "platform", "td_platform");
         showField(test, "kernel", "td_kernel");
-        
+
         String[] labels = Utils.JSONtoStrings(test.get("labels").isArray());
         String labelList = Utils.joinStrings(", ", Arrays.asList(labels));
         if (labelList.equals("")) {
             labelList = "none";
         }
         showText(labelList, "td_test_labels");
-        
         JSONObject attributes = test.get("attributes").isObject();
         RootPanel attributePanel = RootPanel.get("td_attributes");
         attributePanel.clear();
         attributePanel.add(new AttributeTable(attributes));
-        
+        RootPanel analysisPanel = RootPanel.get("td_analysis");
+        analysisPanel.clear();
+        analysisPanel.add(new AnalysisTable(testId));
         logLink.setHref(Utils.getRetrieveLogsUrl(jobTag));
         addLogViewers(testName);
-        
         displayObjectData("Test " + testName + " (job " + jobTag + ")");
     }
     @Override
