2 * Copyright (c) 2010-2022 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.tr064.internal.phonebook;
15 import static org.mockito.ArgumentMatchers.*;
16 import static org.mockito.Mockito.*;
17 import static org.openhab.binding.tr064.internal.Tr064BindingConstants.*;
19 import java.math.BigDecimal;
20 import java.util.Arrays;
21 import java.util.Collection;
22 import java.util.HashMap;
24 import java.util.Optional;
27 import org.eclipse.jdt.annotation.NonNullByDefault;
28 import org.eclipse.jdt.annotation.Nullable;
29 import org.junit.jupiter.api.BeforeEach;
30 import org.junit.jupiter.api.extension.ExtendWith;
31 import org.junit.jupiter.params.ParameterizedTest;
32 import org.junit.jupiter.params.provider.MethodSource;
33 import org.mockito.Mock;
34 import org.mockito.junit.jupiter.MockitoExtension;
35 import org.mockito.junit.jupiter.MockitoSettings;
36 import org.mockito.quality.Strictness;
37 import org.openhab.core.config.core.Configuration;
38 import org.openhab.core.library.types.StringListType;
39 import org.openhab.core.library.types.StringType;
40 import org.openhab.core.thing.ThingUID;
41 import org.openhab.core.thing.profiles.ProfileCallback;
42 import org.openhab.core.thing.profiles.ProfileContext;
43 import org.openhab.core.thing.profiles.StateProfile;
44 import org.openhab.core.types.State;
45 import org.openhab.core.types.UnDefType;
46 import org.openhab.core.util.UIDUtils;
50 * @author Christoph Weitkamp - Initial contribution
52 @ExtendWith(MockitoExtension.class)
53 @MockitoSettings(strictness = Strictness.LENIENT)
55 class PhonebookProfileTest {
57 private static final String INTERNAL_PHONE_NUMBER = "999";
58 private static final String OTHER_PHONE_NUMBER = "555-456";
59 private static final String JOHN_DOES_PHONE_NUMBER = "12345";
60 private static final String JOHN_DOES_NAME = "John Doe";
61 private static final ThingUID THING_UID = new ThingUID(BINDING_ID, THING_TYPE_FRITZBOX.getId(), "test");
62 private static final String MY_PHONEBOOK = UIDUtils.encode(THING_UID.getAsString()) + ":MyPhonebook";
64 public static class ParameterSet {
65 public final State state;
66 public final State resultingState;
67 public final @Nullable Object matchCount;
68 public final @Nullable Object phoneNumberIndex;
70 public ParameterSet(State state, State resultingState, @Nullable Object matchCount,
71 @Nullable Object phoneNumberIndex) {
73 this.resultingState = resultingState;
74 this.matchCount = matchCount;
75 this.phoneNumberIndex = phoneNumberIndex;
79 public static Collection<Object[]> parameters() {
80 return Arrays.asList(new Object[][] { //
81 { new ParameterSet(UnDefType.UNDEF, UnDefType.UNDEF, null, null) }, //
82 { new ParameterSet(new StringType(JOHN_DOES_PHONE_NUMBER), new StringType(JOHN_DOES_NAME), null,
84 { new ParameterSet(new StringType(JOHN_DOES_PHONE_NUMBER), new StringType(JOHN_DOES_NAME),
85 BigDecimal.ONE, null) }, //
86 { new ParameterSet(new StringType(JOHN_DOES_PHONE_NUMBER), new StringType(JOHN_DOES_NAME), "3", null) }, //
87 { new ParameterSet(new StringListType(JOHN_DOES_PHONE_NUMBER, INTERNAL_PHONE_NUMBER),
88 new StringType(JOHN_DOES_NAME), null, null) }, //
89 { new ParameterSet(new StringListType(JOHN_DOES_PHONE_NUMBER, INTERNAL_PHONE_NUMBER),
90 new StringType(JOHN_DOES_NAME), null, BigDecimal.ZERO) }, //
91 { new ParameterSet(new StringListType(INTERNAL_PHONE_NUMBER, JOHN_DOES_PHONE_NUMBER),
92 new StringType(JOHN_DOES_NAME), null, BigDecimal.ONE) }, //
93 { new ParameterSet(new StringType(OTHER_PHONE_NUMBER), new StringType(OTHER_PHONE_NUMBER), null,
95 { new ParameterSet(new StringListType(OTHER_PHONE_NUMBER, INTERNAL_PHONE_NUMBER),
96 new StringType(OTHER_PHONE_NUMBER), null, null) }, //
97 { new ParameterSet(new StringListType(OTHER_PHONE_NUMBER, INTERNAL_PHONE_NUMBER),
98 new StringType(OTHER_PHONE_NUMBER), null, BigDecimal.ZERO) }, //
99 { new ParameterSet(new StringListType(INTERNAL_PHONE_NUMBER, OTHER_PHONE_NUMBER),
100 new StringType(OTHER_PHONE_NUMBER), null, BigDecimal.ONE) }, //
104 private @Mock @NonNullByDefault({}) ProfileCallback mockCallback;
105 private @Mock @NonNullByDefault({}) ProfileContext mockContext;
106 private @Mock @NonNullByDefault({}) PhonebookProvider mockPhonebookProvider;
108 private final Phonebook phonebook = new Phonebook() {
110 public Optional<String> lookupNumber(String number, int matchCount) {
112 case JOHN_DOES_PHONE_NUMBER:
113 return Optional.of(JOHN_DOES_NAME);
115 return Optional.empty();
120 public String getName() {
126 public void setup() {
127 when(mockPhonebookProvider.getPhonebookByName(any(String.class))).thenReturn(Optional.of(phonebook));
128 when(mockPhonebookProvider.getPhonebooks()).thenReturn(Set.of(phonebook));
132 @MethodSource("parameters")
133 public void testPhonebookProfileResolvesPhoneNumber(ParameterSet parameterSet) {
134 StateProfile profile = initProfile(MY_PHONEBOOK, parameterSet.matchCount, parameterSet.phoneNumberIndex);
135 verifySendUpdate(profile, parameterSet.state, parameterSet.resultingState);
138 private StateProfile initProfile(Object phonebookName, @Nullable Object matchCount,
139 @Nullable Object phoneNumberIndex) {
140 Map<String, Object> properties = new HashMap<>();
141 properties.put(PhonebookProfile.PHONEBOOK_PARAM, phonebookName);
142 if (matchCount != null) {
143 properties.put(PhonebookProfile.MATCH_COUNT_PARAM, matchCount);
145 if (phoneNumberIndex != null) {
146 properties.put(PhonebookProfile.PHONE_NUMBER_INDEX_PARAM, phoneNumberIndex);
148 when(mockContext.getConfiguration()).thenReturn(new Configuration(properties));
149 return new PhonebookProfile(mockCallback, mockContext, Map.of(THING_UID, mockPhonebookProvider));
152 private void verifySendUpdate(StateProfile profile, State state, State expectedState) {
154 profile.onStateUpdateFromHandler(state);
155 verify(mockCallback, times(1)).sendUpdate(eq(expectedState));