Skip to content

Commit

Permalink
Add default source functionality and tests (#107)
Browse files Browse the repository at this point in the history
Completes the functionality previously hinted at with the default source function.  This is done by initializing the source setting when it does not exist.  We initialize it with an uninitialized source, which will automatically be initialized when it is opened.  If the source is removed or reset by name, the source list will be empty.  If the all sources are reset, thus deleting the source setting, then the next attempt to get the sources will result in reinitialization from the defaults.

Also adds another field to the source details, IsDefault.  This will give us options in the future to take action on these default sources, such as updating the URL if necessary.  We can write code to transform a source that matches on name and IsDefault being true without any impact to the users.
  • Loading branch information
JohnMcPMS authored May 7, 2020
1 parent 9ce12c7 commit afe95d9
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 83 deletions.
3 changes: 1 addition & 2 deletions src/AppInstallerCLICore/Commands/SourceCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,7 @@ namespace AppInstaller::CLI
{
context <<
Workflow::QueryUserForSourceReset <<
Workflow::ResetAllSources <<
Workflow::AddDefaultSources;
Workflow::ResetAllSources;
}
}
}
6 changes: 0 additions & 6 deletions src/AppInstallerCLICore/Workflows/SourceFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,4 @@ namespace AppInstaller::CLI::Workflow
Repository::DropSource({});
context.Reporter.Info() << " Done." << std::endl;
}

void AddDefaultSources(Execution::Context& context)
{
context.Reporter.Info() << "Adding default sources ..." << std::endl;
context.Reporter.ExecuteWithProgress(Repository::AddDefaultSources);
}
}
14 changes: 4 additions & 10 deletions src/AppInstallerCLICore/Workflows/SourceFlow.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,27 +47,21 @@ namespace AppInstaller::CLI::Workflow
// Outputs: None
void RemoveSources(Execution::Context& context);

// Removes the sources in SourceList.
// Asks the user if they are ok with dropping the sources in SourceList.
// Required Args: None
// Inputs: None
// Inputs: SourceList
// Outputs: None
void QueryUserForSourceReset(Execution::Context& context);

// Removes the sources in SourceList.
// Drops the sources in SourceList.
// Required Args: None
// Inputs: SourceList
// Outputs: None
void ResetSourceList(Execution::Context& context);

// Removes the sources in SourceList.
// Drops all sources.
// Required Args: None
// Inputs: None
// Outputs: None
void ResetAllSources(Execution::Context& context);

// Removes the sources in SourceList.
// Required Args: None
// Inputs: None
// Outputs: None
void AddDefaultSources(Execution::Context& context);
}
2 changes: 1 addition & 1 deletion src/AppInstallerCLICore/Workflows/WorkflowBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ namespace AppInstaller::CLI::Workflow
else
{
// Even if a name was given, there are no sources
context.Reporter.Error() << "No sources defined; add one with 'source add'" << std::endl;
context.Reporter.Error() << "No sources defined; add one with 'source add' or reset to defaults with 'source reset'" << std::endl;
AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_NO_SOURCES_DEFINED);
}
}
Expand Down
7 changes: 0 additions & 7 deletions src/AppInstallerCLIE2ETests/SourceCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,6 @@ public void SourceCommands()
result = TestCommon.RunAICLICommand("source remove", $"-n {SourceTestSourceName}");
Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
Assert.True(result.StdOut.Contains("Done"));

TestCommon.WaitForDeploymentFinish();

// List should show no source available
result = TestCommon.RunAICLICommand("source list", "");
Assert.AreEqual(Constants.ErrorCode.S_OK, result.ExitCode);
Assert.True(result.StdOut.Contains("There are no sources configured."));
}
}
}
58 changes: 51 additions & 7 deletions src/AppInstallerCLITests/Sources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,13 @@ constexpr std::string_view s_ThreeSources = R"(
Arg: testArg
Data: testData
LastUpdate: 0
IsDefault: 1
- Name: testName2
Type: testType2
Arg: testArg2
Data: testData2
LastUpdate: 1
IsDefault: 0
- Name: testName3
Type: testType3
Arg: testArg3
Expand Down Expand Up @@ -143,7 +145,9 @@ TEST_CASE("RepoSources_UserSettingDoesNotExist", "[sources]")
RemoveSetting(s_RepositorySettings_UserSources);

std::vector<SourceDetails> sources = GetSources();
REQUIRE(sources.empty());
// The default source is added when no source exists
REQUIRE(sources.size() == 1);
REQUIRE(sources[0].IsDefault);
}

TEST_CASE("RepoSources_EmptySourcesList", "[sources]")
Expand Down Expand Up @@ -185,6 +189,7 @@ TEST_CASE("RepoSources_ThreeSources", "[sources]")
REQUIRE(sources[i].Arg == "testArg"s + suffix[i]);
REQUIRE(sources[i].Data == "testData"s + suffix[i]);
REQUIRE(sources[i].LastUpdateTime == ConvertUnixEpochToSystemClock(i));
REQUIRE(sources[i].IsDefault == (i == 0));
}
}

Expand All @@ -204,7 +209,7 @@ TEST_CASE("RepoSources_MissingField", "[sources]")

TEST_CASE("RepoSources_AddSource", "[sources]")
{
RemoveSetting(s_RepositorySettings_UserSources);
SetSetting(s_RepositorySettings_UserSources, s_EmptySources);
TestHook_ClearSourceFactoryOverrides();

std::string name = "thisIsTheName";
Expand Down Expand Up @@ -234,7 +239,7 @@ TEST_CASE("RepoSources_AddSource", "[sources]")

TEST_CASE("RepoSources_AddMultipleSources", "[sources]")
{
RemoveSetting(s_RepositorySettings_UserSources);
SetSetting(s_RepositorySettings_UserSources, s_EmptySources);

std::string name = "thisIsTheName";
std::string type = "thisIsTheType";
Expand Down Expand Up @@ -283,7 +288,7 @@ TEST_CASE("RepoSources_UpdateSource", "[sources]")
{
using namespace std::chrono_literals;

RemoveSetting(s_RepositorySettings_UserSources);
SetSetting(s_RepositorySettings_UserSources, s_EmptySources);
TestHook_ClearSourceFactoryOverrides();

std::string name = "thisIsTheName";
Expand Down Expand Up @@ -333,7 +338,7 @@ TEST_CASE("RepoSources_UpdateSourceRetries", "[sources]")
{
using namespace std::chrono_literals;

RemoveSetting(s_RepositorySettings_UserSources);
SetSetting(s_RepositorySettings_UserSources, s_EmptySources);
TestHook_ClearSourceFactoryOverrides();

std::string name = "thisIsTheName";
Expand Down Expand Up @@ -368,7 +373,7 @@ TEST_CASE("RepoSources_UpdateSourceRetries", "[sources]")

TEST_CASE("RepoSources_RemoveSource", "[sources]")
{
RemoveSetting(s_RepositorySettings_UserSources);
SetSetting(s_RepositorySettings_UserSources, s_EmptySources);
TestHook_ClearSourceFactoryOverrides();

std::string name = "thisIsTheName";
Expand Down Expand Up @@ -399,7 +404,6 @@ TEST_CASE("RepoSources_UpdateOnOpen", "[sources]")
{
using namespace std::chrono_literals;

RemoveSetting(s_RepositorySettings_UserSources);
TestHook_ClearSourceFactoryOverrides();

std::string name = "testName";
Expand Down Expand Up @@ -429,3 +433,43 @@ TEST_CASE("RepoSources_UpdateOnOpen", "[sources]")
REQUIRE(sources[0].Data == data);
REQUIRE(sources[0].LastUpdateTime == ConvertUnixEpochToSystemClock(0));
}

TEST_CASE("RepoSources_DropSourceByName", "[sources]")
{
SetSetting(s_RepositorySettings_UserSources, s_ThreeSources);

std::vector<SourceDetails> sources = GetSources();
REQUIRE(sources.size() == 3);

DropSource("testName");

sources = GetSources();
REQUIRE(sources.size() == 2);

const char* suffix[2] = { "2", "3" };

for (size_t i = 0; i < 2; ++i)
{
INFO("Source #" << i);
REQUIRE(sources[i].Name == "testName"s + suffix[i]);
REQUIRE(sources[i].Type == "testType"s + suffix[i]);
REQUIRE(sources[i].Arg == "testArg"s + suffix[i]);
REQUIRE(sources[i].Data == "testData"s + suffix[i]);
REQUIRE(sources[i].LastUpdateTime == ConvertUnixEpochToSystemClock(i + 1));
REQUIRE(!sources[i].IsDefault);
}
}

TEST_CASE("RepoSources_DropAllSources", "[sources]")
{
SetSetting(s_RepositorySettings_UserSources, s_ThreeSources);

std::vector<SourceDetails> sources = GetSources();
REQUIRE(sources.size() == 3);

DropSource({});

sources = GetSources();
REQUIRE(sources.size() == 1);
REQUIRE(sources[0].IsDefault);
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ namespace AppInstaller::Repository

// The last time that this source was updated.
std::chrono::system_clock::time_point LastUpdateTime;

// This source is a default source; added for the user by the tool.
bool IsDefault = false;
};

// Interface for interacting with a source from outside of the repository lib.
Expand All @@ -54,9 +57,6 @@ namespace AppInstaller::Repository
// Adds a new source for the user.
void AddSource(std::string name, std::string type, std::string arg, IProgressCallback& progress);

// Adds the default sources.
void AddDefaultSources(IProgressCallback& progress);

// Opens an existing source.
// Passing an empty string as the name of the source will return a source that aggregates all others.
std::shared_ptr<ISource> OpenSource(std::string_view name, IProgressCallback& progress);
Expand Down
Loading

0 comments on commit afe95d9

Please sign in to comment.