code: // Licensed to the Software Freedom Conservancy (SFC) under one
  // or more contributor license agreements.  See the NOTICE file
  // distributed with this work for additional information
  // regarding copyright ownership.  The SFC licenses this file
  // to you 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 org.openqa.selenium.remote;
  
  import static java.util.Collections.singletonList;
  import static org.assertj.core.api.Assertions.assertThat;
  import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
  import static org.mockito.Mockito.verifyNoMoreInteractions;
  import static org.mockito.Mockito.when;
  
  import com.google.common.collect.ImmutableMap;
  import java.util.ArrayList;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Set;
  import java.util.logging.Level;
  import org.junit.jupiter.api.BeforeEach;
  import org.junit.jupiter.api.Tag;
  import org.junit.jupiter.api.Test;
  import org.mockito.Mock;
  import org.mockito.MockitoAnnotations;
  import org.openqa.selenium.WebDriverException;
  import org.openqa.selenium.logging.LocalLogs;
  import org.openqa.selenium.logging.LogEntries;
  import org.openqa.selenium.logging.LogEntry;
  import org.openqa.selenium.logging.LogType;
  
  @Tag("UnitTests")
  class RemoteLogsTest {
    @Mock private ExecuteMethod executeMethod;
  
    @Mock private LocalLogs localLogs;
  
    private RemoteLogs remoteLogs;
  
    @BeforeEach
    public void createMocksAndRemoteLogs() {
      MockitoAnnotations.initMocks(this);
      remoteLogs = new RemoteLogs(executeMethod, localLogs);
    }
  
    @Test
    void canGetProfilerLogs() {
      List<LogEntry> entries = new ArrayList<>();
      entries.add(new LogEntry(Level.INFO, 0, "hello"));
      when(localLogs.get(LogType.PROFILER)).thenReturn(new LogEntries(entries));
  
      when(executeMethod.execute(
              DriverCommand.GET_LOG, ImmutableMap.of(RemoteLogs.TYPE_KEY, LogType.PROFILER)))
          .thenReturn(
              singletonList(
                  ImmutableMap.of(
                      "level", Level.INFO.getName(), "timestamp", 1L, "message", "world")));
  
      LogEntries logEntries = remoteLogs.get(LogType.PROFILER);
      List<LogEntry> allLogEntries = logEntries.getAll();
      assertThat(allLogEntries).hasSize(2);
      assertThat(allLogEntries.get(0).getMessage()).isEqualTo("hello");
      assertThat(allLogEntries.get(1).getMessage()).isEqualTo("world");
    }
  
    @Test
    void canGetLocalProfilerLogsIfNoRemoteProfilerLogSupport() {
      List<LogEntry> entries = new ArrayList<>();
      entries.add(new LogEntry(Level.INFO, 0, "hello"));
      when(localLogs.get(LogType.PROFILER)).thenReturn(new LogEntries(entries));
  
      when(executeMethod.execute(
              DriverCommand.GET_LOG, ImmutableMap.of(RemoteLogs.TYPE_KEY, LogType.PROFILER)))
          .thenThrow(
              new WebDriverException("IGNORE THIS LOG MESSAGE AND STACKTRACE; IT IS EXPECTED."));
  
      LogEntries logEntries = remoteLogs.get(LogType.PROFILER);
      List<LogEntry> allLogEntries = logEntries.getAll();
      assertThat(allLogEntries).hasSize(1);
      assertThat(allLogEntries.get(0).getMessage()).isEqualTo("hello");
    }
  
    @Test
    void canGetClientLogs() {
      List<LogEntry> entries = new ArrayList<>();
      entries.add(new LogEntry(Level.SEVERE, 0, "hello"));
      when(localLogs.get(LogType.CLIENT)).thenReturn(new LogEntries(entries));
  
      LogEntries logEntries = remoteLogs.get(LogType.CLIENT);
      assertThat(logEntries.getAll()).hasSize(1);
      assertThat(logEntries.getAll().get(0).getMessage()).isEqualTo("hello");
  
      // Client logs should not retrieve remote logs.
      verifyNoMoreInteractions(executeMethod);
    }
  
    @Test
    void canGetServerLogs() {
      when(executeMethod.execute(
              DriverCommand.GET_LOG, ImmutableMap.of(RemoteLogs.TYPE_KEY, LogType.SERVER)))
          .thenReturn(
              singletonList(
                  ImmutableMap.of(
                      "level", Level.INFO.getName(), "timestamp", 0L, "message", "world")));
  
      LogEntries logEntries = remoteLogs.get(LogType.SERVER);
      assertThat(logEntries.getAll()).hasSize(1);
      assertThat(logEntries.getAll().get(0).getMessage()).isEqualTo("world");
  
      // Server logs should not retrieve local logs.
      verifyNoMoreInteractions(localLogs);
    }
  
    @Test
    void throwsOnBogusRemoteLogsResponse() {
      when(executeMethod.execute(
              DriverCommand.GET_LOG, ImmutableMap.of(RemoteLogs.TYPE_KEY, LogType.BROWSER)))
          .thenReturn(
              ImmutableMap.of(
                  "error", "unknown method",
                  "message", "Command not found: POST /session/11037/log",
                  "stacktrace", ""));
  
      assertThatExceptionOfType(WebDriverException.class)
          .isThrownBy(() -> remoteLogs.get(LogType.BROWSER));
  
      verifyNoMoreInteractions(localLogs);
    }
  
    @Test
    void canGetAvailableLogTypes() {
      List<String> remoteAvailableLogTypes = new ArrayList<>();
      remoteAvailableLogTypes.add(LogType.PROFILER);
      remoteAvailableLogTypes.add(LogType.SERVER);
  
      when(executeMethod.execute(DriverCommand.GET_AVAILABLE_LOG_TYPES, null))
          .thenReturn(remoteAvailableLogTypes);
  
      Set<String> localAvailableLogTypes = new HashSet<>();
      localAvailableLogTypes.add(LogType.PROFILER);
      localAvailableLogTypes.add(LogType.CLIENT);
  
      when(localLogs.getAvailableLogTypes()).thenReturn(localAvailableLogTypes);
  
      Set<String> expected = new HashSet<>();
      expected.add(LogType.CLIENT);
      expected.add(LogType.PROFILER);
      expected.add(LogType.SERVER);
  
      Set<String> availableLogTypes = remoteLogs.getAvailableLogTypes();
  
      assertThat(availableLogTypes).isEqualTo(expected);
    }
  }
  