Improve coverage of cadi-core 33/47833/1
authorIanHowell <ian.howell@att.com>
Wed, 16 May 2018 14:14:10 +0000 (09:14 -0500)
committerIanHowell <ian.howell@att.com>
Wed, 16 May 2018 14:14:22 +0000 (09:14 -0500)
* Reduced complexity of HttpEpiTaf and LoginPageTafResp
* Applied ONAP's code style to HttpEpiTaf and LoginPageTafResp
* wrote JUnits for HttpEpiTaf and LoginPageTafResp

Issue-ID: AAF-225
Change-Id: I28059237e838d0276593d556d2e04fe3a7b852c6
Signed-off-by: IanHowell <ian.howell@att.com>
cadi/core/src/main/java/org/onap/aaf/cadi/taf/HttpEpiTaf.java
cadi/core/src/main/java/org/onap/aaf/cadi/taf/LoginPageTafResp.java
cadi/core/src/test/java/org/onap/aaf/cadi/taf/test/JU_HttpEpiTaf.java [new file with mode: 0644]
cadi/core/src/test/java/org/onap/aaf/cadi/taf/test/JU_LoginPageTafResp.java [new file with mode: 0644]

index cc28397..5cd6323 100644 (file)
@@ -7,9 +7,9 @@
  * 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.
@@ -40,9 +40,9 @@ import org.onap.aaf.cadi.TrustChecker;
 
 /**
  * HttpEpiTaf
- * 
+ *
  * An extension of the basic "EpiTAF" concept, check known HTTP Related TAFs for valid credentials
- * 
+ *
  * @author Jonathan
  *
  */
@@ -51,10 +51,10 @@ public class HttpEpiTaf implements HttpTaf {
        private Access access;
        private Locator<URI> locator;
        private TrustChecker trustChecker;
-       
+
        /**
         * HttpEpiTaf constructor
-        * 
+        *
         * Construct the HttpEpiTaf from variable Http specific TAF parameters
 
         * @param tafs
@@ -65,52 +65,52 @@ public class HttpEpiTaf implements HttpTaf {
                this.access = access;
                this.locator = locator;
                this.trustChecker = tc;
-               // Establish what Header Property to look for UserChain/Trust Props 
-//             trustChainProp = access.getProperty(Config.CADI_TRUST_PROP, Config.CADI_TRUST_PROP_DEFAULT);
+               // Establish what Header Property to look for UserChain/Trust Props
 
-               if(tafs.length==0) throw new CadiException("Need at least one HttpTaf implementation in constructor");
+               if (tafs.length == 0) {
+                       throw new CadiException("Need at least one HttpTaf implementation in constructor");
+               }
        }
 
        /**
         * validate
-        * 
-        * Respond with the first Http specific TAF to authenticate user based on variable info 
+        *
+        * Respond with the first Http specific TAF to authenticate user based on variable info
         * and "LifeForm" (is it a human behind a browser, or a server utilizing HTTP Protocol).
-        * 
+        *
         * If there is no HttpTAF that can authenticate, respond with the first TAF that suggests it can
         * establish an Authentication conversation (TRY_AUTHENTICATING) (Examples include a redirect to CSP
-        * Servers for CSP Cookie, or BasicAuth 401 response, suggesting User/Password for given Realm 
+        * Servers for CSP Cookie, or BasicAuth 401 response, suggesting User/Password for given Realm
         * submission
-        * 
+        *
         * If no TAF declares either, respond with NullTafResp (which denies all questions)
         */
        public TafResp validate(LifeForm reading, HttpServletRequest req, HttpServletResponse resp) {
                // Given a LifeForm Neutral, for HTTP, we need to discover true Life-Form Readings
-               if(reading==LifeForm.LFN) {
+               if (reading == LifeForm.LFN) {
                        reading = tricorderScan(req);
                }
-               TafResp tresp=null, firstTry = null;
+               TafResp tresp = null;
+               TafResp firstTry = null;
                List<Redirectable> redirectables = null;
-               List<TafResp> trlog = access.willLog(Level.DEBUG)?new ArrayList<TafResp>():null;
+               List<TafResp> log = (access.willLog(Level.DEBUG)) ? new ArrayList<TafResp>() : null;
                try {
-                       for(HttpTaf taf : tafs) {
+                       for (HttpTaf taf : tafs) {
                                tresp = taf.validate(reading, req, resp);
-                               if(trlog!=null) {
-                                       trlog.add(tresp);
-                               }
+                               addToLog(log, tresp);
                                switch(tresp.isAuthenticated()) {
                                        case TRY_ANOTHER_TAF:
                                                break; // and loop
                                        case TRY_AUTHENTICATING:
-                                               if(tresp instanceof Redirectable) {
-                                                       if(redirectables==null) {
-                                                               redirectables = new ArrayList<Redirectable>();
+                                               if (tresp instanceof Redirectable) {
+                                                       if (redirectables == null) {
+                                                               redirectables = new ArrayList<>();
                                                        }
                                                        redirectables.add((Redirectable)tresp);
-                                               } else if(firstTry==null) {
+                                               } else if (firstTry == null) {
                                                        firstTry = tresp;
                                                }
-                                               break; 
+                                               break;
                                        case IS_AUTHENTICATED:
                                                tresp = trustChecker.mayTrust(tresp, req);
                                                return tresp;
@@ -118,46 +118,42 @@ public class HttpEpiTaf implements HttpTaf {
                                                return tresp;
                                }
                        }
-               } finally {             
-                       if(trlog!=null) {
-                               for( TafResp tr : trlog) {
-                                       access.log(Level.DEBUG, tr.desc());
-                               }
-                       }
+               } finally {
+                       printLog(log);
                }
-               
-               // If No TAFs configured, at this point.  It is safer at this point to be "not validated", 
+
+               // If No TAFs configured, at this point.  It is safer at this point to be "not validated",
                // rather than "let it go"
                // Note: if exists, there will always be more than 0 entries, according to above code
-               if(redirectables==null) {
-                       return firstTry!=null?firstTry:NullTafResp.singleton();
+               if (redirectables == null) {
+                       return (firstTry != null) ? firstTry : NullTafResp.singleton();
                }
-               
+
                // If there is one Tryable entry then return it
-               if(redirectables.size()>1) {
-                       return LoginPageTafResp.create(access,locator,resp,redirectables);
+               if (redirectables.size() > 1) {
+                       return LoginPageTafResp.create(access, locator, resp, redirectables);
                } else {
                        return redirectables.get(0);
                }
        }
-       
+
        public boolean revalidate(Principal prin) throws Exception {
                return false;
        }
 
        /*
         * Since this is internal, we use a little Star Trek humor to indicate looking in the HTTP Request to see if we can determine what kind
-        * of "LifeForm" reading we can determine, i.e. is there a Human (CarbonBasedLifeForm) behind a browser, or is it mechanical 
+        * of "LifeForm" reading we can determine, i.e. is there a Human (CarbonBasedLifeForm) behind a browser, or is it mechanical
         * id (SiliconBasedLifeForm)?  This makes a difference in some Authentication, i.e CSP, which doesn't work well for SBLFs
         */
        private LifeForm tricorderScan(HttpServletRequest req) {
                // For simplicity's sake, we'll say Humans use FQDNs, not IPs.
-               
+
                // Current guess that only Browsers bother to set "Agent" codes that identify the kind of browser they are.
                // If mechanical frameworks are found that populate this, then more advanced analysis may be required
                // Jonathan 1/22/2013
                String agent = req.getHeader("User-Agent");
-               if(agent!=null && agent.startsWith("Mozilla")) { // covers I.E./Firefox/Safari/probably any other "advanced" Browser see http://en.wikipedia.org/wiki/User_agent
+               if (agent != null && agent.startsWith("Mozilla")) { // covers I.E./Firefox/Safari/probably any other "advanced" Browser see http://en.wikipedia.org/wiki/User_agent
                        return LifeForm.CBLF;
                }
                return LifeForm.SBLF;                                                   // notably skips "curl","wget", (which is desired behavior.  We don't want to try CSP, etc on these)
@@ -165,17 +161,36 @@ public class HttpEpiTaf implements HttpTaf {
 
        public Resp revalidate(CachedPrincipal prin, Object state) {
                Resp resp;
-               for(HttpTaf taf : tafs) {
-                       resp = taf.revalidate(prin,state);
-                       switch(resp) {
-                               case NOT_MINE:
-                                       break;
-                               default:
-                                       return resp;
+               for (HttpTaf taf : tafs) {
+                       resp = taf.revalidate(prin, state);
+                       if (resp != Resp.NOT_MINE) {
+                               return resp;
                        }
+//                     switch(resp) {
+//                             case NOT_MINE:
+//                                     break;
+//                             default:
+//                                     return resp;
+//                     }
                }
                return Resp.NOT_MINE;
        }
+       
+       private void addToLog(List<TafResp> log, TafResp tresp) {
+               if (log == null) {
+                       return;
+               }
+               log.add(tresp);
+       }
+       
+       private void printLog(List<TafResp> log) {
+               if (log == null) {
+                       return;
+               }
+               for (TafResp tresp : log) {
+                       access.log(Level.DEBUG, tresp.desc());
+               }
+       }
 
        /**
         * List HttpTafs with their "toString" representations... primarily useful for Debugging in an IDE
@@ -183,7 +198,7 @@ public class HttpEpiTaf implements HttpTaf {
         */
        public String toString() {
                StringBuilder sb = new StringBuilder();
-               for(HttpTaf ht : tafs) {
+               for (HttpTaf ht : tafs) {
                        sb.append(ht.toString());
                        sb.append(". ");
                }
index 9c9cbc2..3f80170 100644 (file)
@@ -53,34 +53,42 @@ public class LoginPageTafResp extends AbsTafResp {
                return RESP.TRY_AUTHENTICATING;
        }
        
-       public static TafResp create(Access access, Locator<URI> locator, final HttpServletResponse resp, List<Redirectable> redir) {
-               if(locator!=null) {
-                       try {
-                               Item item = locator.best();
-                               URI uri = locator.get(item);
-                               if(uri!=null) {
-                                       StringBuilder sb = new StringBuilder(uri.toString());
-                                       String query = uri.getQuery();
-                                       boolean first = query==null || query.length()==0;
-                                       int count=0;
-                                       for(Redirectable t : redir) {
-                                               if(first) {
-                                                       sb.append('?');
-                                                       first=false;
-                                               }
-                                               else sb.append('&');
-                                               sb.append(t.get());
-                                               ++count;
-                                       }
-                                       if(count>0)return new LoginPageTafResp(access, resp, sb.toString());
+       public static TafResp create(Access access, Locator<URI> locator, final HttpServletResponse resp, List<Redirectable> redirectables) {
+               if (locator == null) {
+                       if (!redirectables.isEmpty()) { 
+                               access.log(Level.DEBUG,"LoginPage Locator is not configured. Taking first Redirectable Taf");
+                               return redirectables.get(0);
+                       }
+                       return NullTafResp.singleton();
+               }
+
+               try {
+                       Item item = locator.best();
+                       URI uri = locator.get(item);
+                       if (uri == null) {
+                               return NullTafResp.singleton();
+                       }
+
+                       StringBuilder sb = new StringBuilder(uri.toString());
+                       String query = uri.getQuery();
+                       boolean first = ((query == null) || (query.length() == 0));
+                       for (Redirectable redir : redirectables) {
+                               if (first) {
+                                       sb.append('?');
+                                       first = false;
+                               }
+                               else {
+                                       sb.append('&');
                                }
-                       } catch (Exception e) {
-                               access.log(e, "Error deriving Login Page location");
+                               sb.append(redir.get());
                        }
-               } else if(!redir.isEmpty()) { 
-                       access.log(Level.DEBUG,"LoginPage Locator is not configured. Taking first Redirectable Taf");
-                       return redir.get(0);
+                       if (!redirectables.isEmpty()) {
+                               return new LoginPageTafResp(access, resp, sb.toString());
+                       }
+               } catch (Exception e) {
+                       access.log(e, "Error deriving Login Page location");
                }
+
                return NullTafResp.singleton();
        }
 }
diff --git a/cadi/core/src/test/java/org/onap/aaf/cadi/taf/test/JU_HttpEpiTaf.java b/cadi/core/src/test/java/org/onap/aaf/cadi/taf/test/JU_HttpEpiTaf.java
new file mode 100644 (file)
index 0000000..93a2047
--- /dev/null
@@ -0,0 +1,145 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * 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.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.cadi.taf.test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.aaf.cadi.Access.Level;
+import org.onap.aaf.cadi.CachedPrincipal.Resp;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.Locator;
+import org.onap.aaf.cadi.PropAccess;
+import org.onap.aaf.cadi.Taf.LifeForm;
+import org.onap.aaf.cadi.TrustChecker;
+import org.onap.aaf.cadi.taf.HttpEpiTaf;
+import org.onap.aaf.cadi.taf.HttpTaf;
+import org.onap.aaf.cadi.taf.NullTaf;
+import org.onap.aaf.cadi.taf.Redirectable;
+import org.onap.aaf.cadi.taf.TafResp;
+import org.onap.aaf.cadi.taf.TafResp.RESP;
+
+public class JU_HttpEpiTaf {
+
+       private PropAccess access;
+
+       @Mock private Locator<URI> locMock;
+       @Mock private TrustChecker trustCheckerMock;
+       @Mock private HttpServletRequest reqMock;
+       @Mock private HttpServletResponse respMock;
+       @Mock private HttpTaf tafMock;
+       @Mock private TafResp trespMock;
+       @Mock private Redirectable redirMock;
+
+       @Before
+       public void setup() throws URISyntaxException {
+               MockitoAnnotations.initMocks(this);
+
+               access = new PropAccess(new PrintStream(new ByteArrayOutputStream()), new String[0]);
+       }
+
+       @Test
+       public void test() throws Exception {
+               HttpEpiTaf taf;
+               try {
+                       taf = new HttpEpiTaf(access, locMock, trustCheckerMock);
+                       fail("Should've thrown an exception");
+               } catch (CadiException e) {
+                       assertThat(e.getMessage(), is("Need at least one HttpTaf implementation in constructor"));
+               }
+
+               taf = new HttpEpiTaf(access, locMock, trustCheckerMock, new NullTaf());
+               taf.validate(LifeForm.CBLF, reqMock, respMock);
+
+               // Coverage of tricorderScan
+               taf.validate(LifeForm.LFN, reqMock, respMock);
+               when(reqMock.getHeader("User-Agent")).thenReturn("Non-mozilla-header");
+               taf.validate(LifeForm.LFN, reqMock, respMock);
+               when(reqMock.getHeader("User-Agent")).thenReturn("Mozilla-header");
+               taf.validate(LifeForm.LFN, reqMock, respMock);
+
+               access.setLogLevel(Level.DEBUG);
+               taf.validate(LifeForm.CBLF, reqMock, respMock);
+
+               when(tafMock.validate(LifeForm.CBLF, reqMock, respMock)).thenReturn(trespMock);
+               when(trespMock.isAuthenticated()).thenReturn(RESP.TRY_ANOTHER_TAF);
+               taf = new HttpEpiTaf(access, locMock, trustCheckerMock, tafMock);
+               taf.validate(LifeForm.CBLF, reqMock, respMock);
+
+               when(trespMock.isAuthenticated()).thenReturn(RESP.IS_AUTHENTICATED);
+               taf.validate(LifeForm.CBLF, reqMock, respMock);
+
+               when(trespMock.isAuthenticated()).thenReturn(RESP.TRY_AUTHENTICATING);
+               taf.validate(LifeForm.CBLF, reqMock, respMock);
+
+               taf = new HttpEpiTaf(access, locMock, trustCheckerMock, tafMock, tafMock);
+               taf.validate(LifeForm.CBLF, reqMock, respMock);
+
+               when(tafMock.validate(LifeForm.CBLF, reqMock, respMock)).thenReturn(redirMock);
+               when(redirMock.isAuthenticated()).thenReturn(RESP.TRY_AUTHENTICATING);
+               taf.validate(LifeForm.CBLF, reqMock, respMock);
+
+               taf = new HttpEpiTaf(access, locMock, trustCheckerMock, tafMock, tafMock);
+               taf.validate(LifeForm.CBLF, reqMock, respMock);
+
+               taf = new HttpEpiTaf(access, locMock, trustCheckerMock, tafMock);
+               taf.validate(LifeForm.CBLF, reqMock, respMock);
+
+               taf = new HttpEpiTaf(access, locMock, null, tafMock);
+               when(redirMock.isAuthenticated()).thenReturn(RESP.IS_AUTHENTICATED);
+               try {
+                       taf.validate(LifeForm.CBLF, reqMock, respMock);
+                       fail("Should've thrown an exception");
+               } catch (Exception e) {
+               }
+
+               assertThat(taf.revalidate(null), is(false));
+               assertThat(taf.revalidate(null), is(false));
+
+               when(tafMock.revalidate(null, null)).thenReturn(Resp.NOT_MINE);
+               assertThat(taf.revalidate(null, null), is(Resp.NOT_MINE));
+               when(tafMock.revalidate(null, null)).thenReturn(Resp.REVALIDATED);
+               assertThat(taf.revalidate(null, null), is(Resp.REVALIDATED));
+
+               when(tafMock.revalidate(null, null)).thenReturn(Resp.NOT_MINE).thenReturn(Resp.NOT_MINE).thenReturn(Resp.REVALIDATED);
+               taf = new HttpEpiTaf(access, locMock, trustCheckerMock, tafMock, tafMock, tafMock);
+               assertThat(taf.revalidate(null, null), is(Resp.REVALIDATED));
+
+               taf.toString();
+
+       }
+
+}
diff --git a/cadi/core/src/test/java/org/onap/aaf/cadi/taf/test/JU_LoginPageTafResp.java b/cadi/core/src/test/java/org/onap/aaf/cadi/taf/test/JU_LoginPageTafResp.java
new file mode 100644 (file)
index 0000000..3124bbd
--- /dev/null
@@ -0,0 +1,101 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * 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.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.cadi.taf.test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.aaf.cadi.Access;
+import org.onap.aaf.cadi.Locator;
+import org.onap.aaf.cadi.Locator.Item;
+import org.onap.aaf.cadi.LocatorException;
+import org.onap.aaf.cadi.PropAccess;
+import org.onap.aaf.cadi.taf.LoginPageTafResp;
+import org.onap.aaf.cadi.taf.Redirectable;
+import org.onap.aaf.cadi.taf.TafResp;
+import org.onap.aaf.cadi.taf.TafResp.RESP;
+
+public class JU_LoginPageTafResp {
+
+       private static final String uriString = "example.com";
+
+       private URI uri;
+       private Access access;
+       private List<Redirectable> redirectables;
+
+       @Mock private HttpServletResponse respMock;
+       @Mock private Locator<URI> locatorMock;
+       @Mock private Redirectable redirMock;
+
+       @Before
+       public void setup() throws URISyntaxException {
+               MockitoAnnotations.initMocks(this);
+
+               access = new PropAccess(new PrintStream(new ByteArrayOutputStream()), new String[0]);
+
+               redirectables = new ArrayList<>();
+               uri = new URI(uriString);
+       }
+
+       @Test
+       public void test() throws LocatorException, IOException {
+               TafResp resp;
+               resp = LoginPageTafResp.create(access, null, respMock, redirectables);
+               assertThat(resp.desc(), is("All Authentication denied"));
+
+               redirectables.add(redirMock);
+               redirectables.add(redirMock);
+               resp = LoginPageTafResp.create(access, null, respMock, redirectables);
+               assertThat((Redirectable)resp, is(redirMock));
+
+               resp = LoginPageTafResp.create(access, locatorMock, respMock, redirectables);
+               assertThat(resp.desc(), is("All Authentication denied"));
+
+               when(locatorMock.get((Item)any())).thenReturn(uri);
+               resp = LoginPageTafResp.create(access, locatorMock, respMock, redirectables);
+               assertThat(resp.desc(), is("Multiple Possible HTTP Logins available.  Redirecting to Login Choice Page"));
+               assertThat(resp.authenticate(), is(RESP.HTTP_REDIRECT_INVOKED));
+               assertThat(resp.isAuthenticated(), is(RESP.TRY_AUTHENTICATING));
+
+               redirectables = new ArrayList<>();
+               resp = LoginPageTafResp.create(access, locatorMock, respMock, redirectables);
+               assertThat(resp.desc(), is("All Authentication denied"));
+
+       }
+
+}