Initial Commit
This commit is contained in:
commit
e6a48b8c0e
25 changed files with 2654 additions and 0 deletions
12
Makefile
Normal file
12
Makefile
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
.PHONY: clean All
|
||||
|
||||
All:
|
||||
@echo "----------Building project:[ UOCContacts - Debug ]----------"
|
||||
@cd "UOCContacts" && "$(MAKE)" -f "UOCContacts.mk"
|
||||
@echo "----------Building project:[ UOC20211 - Debug ]----------"
|
||||
@"$(MAKE)" -f "UOC20211.mk"
|
||||
clean:
|
||||
@echo "----------Cleaning project:[ UOCContacts - Debug ]----------"
|
||||
@cd "UOCContacts" && "$(MAKE)" -f "UOCContacts.mk" clean
|
||||
@echo "----------Cleaning project:[ UOC20211 - Debug ]----------"
|
||||
@"$(MAKE)" -f "UOC20211.mk" clean
|
||||
4
README.txt
Normal file
4
README.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
gsboeck@uoc.edu
|
||||
Solà i Boeck, Guillem
|
||||
Fedora release 34 (Thirty Four) x86_64
|
||||
gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC)
|
||||
143
UOC20211.mk
Normal file
143
UOC20211.mk
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
##
|
||||
## Auto Generated makefile by CodeLite IDE
|
||||
## any manual changes will be erased
|
||||
##
|
||||
## Debug
|
||||
ProjectName :=UOC20211
|
||||
ConfigurationName :=Debug
|
||||
WorkspacePath :=W:/Docencia/PP/20211/PR1/UOC20211
|
||||
ProjectPath :=W:/Docencia/PP/20211/PR1/UOC20211
|
||||
IntermediateDirectory :=./bin/Debug
|
||||
OutDir := $(IntermediateDirectory)
|
||||
CurrentFileName :=
|
||||
CurrentFilePath :=
|
||||
CurrentFileFullPath :=
|
||||
User :=xavie
|
||||
Date :=11/10/2021
|
||||
CodeLitePath :="C:/Program Files/CodeLite"
|
||||
LinkerName :=C:/TDM-GCC-64/bin/g++.exe
|
||||
SharedObjectLinkerName :=C:/TDM-GCC-64/bin/g++.exe -shared -fPIC
|
||||
ObjectSuffix :=.o
|
||||
DependSuffix :=.o.d
|
||||
PreprocessSuffix :=.i
|
||||
DebugSwitch :=-g
|
||||
IncludeSwitch :=-I
|
||||
LibrarySwitch :=-l
|
||||
OutputSwitch :=-o
|
||||
LibraryPathSwitch :=-L
|
||||
PreprocessorSwitch :=-D
|
||||
SourceSwitch :=-c
|
||||
OutputFile :=./bin/$(ProjectName)d
|
||||
Preprocessors :=
|
||||
ObjectSwitch :=-o
|
||||
ArchiveOutputSwitch :=
|
||||
PreprocessOnlySwitch :=-E
|
||||
ObjectsFileList :="UOC20211.txt"
|
||||
PCHCompileFlags :=
|
||||
MakeDirCommand :=makedir
|
||||
RcCmpOptions :=
|
||||
RcCompilerName :=C:/TDM-GCC-64/bin/windres.exe
|
||||
LinkOptions :=
|
||||
IncludePath := $(IncludeSwitch). $(IncludeSwitch). $(IncludeSwitch)test/include $(IncludeSwitch)UOCContacts/include
|
||||
IncludePCH :=
|
||||
RcIncludePath :=
|
||||
Libs := $(LibrarySwitch)UOCContactsd
|
||||
ArLibs := "libUOCContactsd.a"
|
||||
LibPath := $(LibraryPathSwitch). $(LibraryPathSwitch)./lib
|
||||
|
||||
##
|
||||
## Common variables
|
||||
## AR, CXX, CC, AS, CXXFLAGS and CFLAGS can be overriden using an environment variables
|
||||
##
|
||||
AR := C:/TDM-GCC-64/bin/ar.exe rcu
|
||||
CXX := C:/TDM-GCC-64/bin/g++.exe
|
||||
CC := C:/TDM-GCC-64/bin/gcc.exe
|
||||
CXXFLAGS := -g -O0 -Wall $(Preprocessors)
|
||||
CFLAGS := -g -O0 -Wall $(Preprocessors)
|
||||
ASFLAGS :=
|
||||
AS := C:/TDM-GCC-64/bin/as.exe
|
||||
|
||||
|
||||
##
|
||||
## User defined environment variables
|
||||
##
|
||||
CodeLiteDir:=C:\Program Files\CodeLite
|
||||
Objects0=$(IntermediateDirectory)/src_main.c$(ObjectSuffix) $(IntermediateDirectory)/test_src_test_suite.c$(ObjectSuffix) $(IntermediateDirectory)/test_src_test.c$(ObjectSuffix) $(IntermediateDirectory)/test_src_test_pr1.c$(ObjectSuffix)
|
||||
|
||||
|
||||
|
||||
Objects=$(Objects0)
|
||||
|
||||
##
|
||||
## Main Build Targets
|
||||
##
|
||||
.PHONY: all clean PreBuild PrePreBuild PostBuild MakeIntermediateDirs
|
||||
all: $(OutputFile)
|
||||
|
||||
$(OutputFile): $(IntermediateDirectory)/.d ".build-debug\UOCContacts" $(Objects)
|
||||
@$(MakeDirCommand) $(@D)
|
||||
@echo "" > $(IntermediateDirectory)/.d
|
||||
@echo $(Objects0) > $(ObjectsFileList)
|
||||
$(LinkerName) $(OutputSwitch)$(OutputFile) @$(ObjectsFileList) $(LibPath) $(Libs) $(LinkOptions)
|
||||
|
||||
".build-debug\UOCContacts":
|
||||
@$(MakeDirCommand) ".build-debug"
|
||||
@echo stam > ".build-debug\UOCContacts"
|
||||
|
||||
|
||||
|
||||
|
||||
MakeIntermediateDirs:
|
||||
@$(MakeDirCommand) "./bin/Debug"
|
||||
|
||||
|
||||
$(IntermediateDirectory)/.d:
|
||||
@$(MakeDirCommand) "./bin/Debug"
|
||||
|
||||
PreBuild:
|
||||
|
||||
|
||||
##
|
||||
## Objects
|
||||
##
|
||||
$(IntermediateDirectory)/src_main.c$(ObjectSuffix): src/main.c $(IntermediateDirectory)/src_main.c$(DependSuffix)
|
||||
$(CC) $(SourceSwitch) "W:/Docencia/PP/20211/PR1/UOC20211/src/main.c" $(CFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/src_main.c$(ObjectSuffix) $(IncludePath)
|
||||
$(IntermediateDirectory)/src_main.c$(DependSuffix): src/main.c
|
||||
@$(CC) $(CFLAGS) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/src_main.c$(ObjectSuffix) -MF$(IntermediateDirectory)/src_main.c$(DependSuffix) -MM src/main.c
|
||||
|
||||
$(IntermediateDirectory)/src_main.c$(PreprocessSuffix): src/main.c
|
||||
$(CC) $(CFLAGS) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/src_main.c$(PreprocessSuffix) src/main.c
|
||||
|
||||
$(IntermediateDirectory)/test_src_test_suite.c$(ObjectSuffix): test/src/test_suite.c $(IntermediateDirectory)/test_src_test_suite.c$(DependSuffix)
|
||||
$(CC) $(SourceSwitch) "W:/Docencia/PP/20211/PR1/UOC20211/test/src/test_suite.c" $(CFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/test_src_test_suite.c$(ObjectSuffix) $(IncludePath)
|
||||
$(IntermediateDirectory)/test_src_test_suite.c$(DependSuffix): test/src/test_suite.c
|
||||
@$(CC) $(CFLAGS) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/test_src_test_suite.c$(ObjectSuffix) -MF$(IntermediateDirectory)/test_src_test_suite.c$(DependSuffix) -MM test/src/test_suite.c
|
||||
|
||||
$(IntermediateDirectory)/test_src_test_suite.c$(PreprocessSuffix): test/src/test_suite.c
|
||||
$(CC) $(CFLAGS) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/test_src_test_suite.c$(PreprocessSuffix) test/src/test_suite.c
|
||||
|
||||
$(IntermediateDirectory)/test_src_test.c$(ObjectSuffix): test/src/test.c $(IntermediateDirectory)/test_src_test.c$(DependSuffix)
|
||||
$(CC) $(SourceSwitch) "W:/Docencia/PP/20211/PR1/UOC20211/test/src/test.c" $(CFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/test_src_test.c$(ObjectSuffix) $(IncludePath)
|
||||
$(IntermediateDirectory)/test_src_test.c$(DependSuffix): test/src/test.c
|
||||
@$(CC) $(CFLAGS) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/test_src_test.c$(ObjectSuffix) -MF$(IntermediateDirectory)/test_src_test.c$(DependSuffix) -MM test/src/test.c
|
||||
|
||||
$(IntermediateDirectory)/test_src_test.c$(PreprocessSuffix): test/src/test.c
|
||||
$(CC) $(CFLAGS) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/test_src_test.c$(PreprocessSuffix) test/src/test.c
|
||||
|
||||
$(IntermediateDirectory)/test_src_test_pr1.c$(ObjectSuffix): test/src/test_pr1.c $(IntermediateDirectory)/test_src_test_pr1.c$(DependSuffix)
|
||||
$(CC) $(SourceSwitch) "W:/Docencia/PP/20211/PR1/UOC20211/test/src/test_pr1.c" $(CFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/test_src_test_pr1.c$(ObjectSuffix) $(IncludePath)
|
||||
$(IntermediateDirectory)/test_src_test_pr1.c$(DependSuffix): test/src/test_pr1.c
|
||||
@$(CC) $(CFLAGS) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/test_src_test_pr1.c$(ObjectSuffix) -MF$(IntermediateDirectory)/test_src_test_pr1.c$(DependSuffix) -MM test/src/test_pr1.c
|
||||
|
||||
$(IntermediateDirectory)/test_src_test_pr1.c$(PreprocessSuffix): test/src/test_pr1.c
|
||||
$(CC) $(CFLAGS) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/test_src_test_pr1.c$(PreprocessSuffix) test/src/test_pr1.c
|
||||
|
||||
|
||||
-include $(IntermediateDirectory)/*$(DependSuffix)
|
||||
##
|
||||
## Clean
|
||||
##
|
||||
clean:
|
||||
$(RM) -r ./bin/Debug/
|
||||
|
||||
|
||||
140
UOC20211.project
Normal file
140
UOC20211.project
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CodeLite_Project Name="UOC20211" Version="10.0.0" InternalType="Console">
|
||||
<Plugins>
|
||||
<Plugin Name="qmake">
|
||||
<![CDATA[00020001N0005Debug0000000000000001N0007Release000000000000]]>
|
||||
</Plugin>
|
||||
</Plugins>
|
||||
<VirtualDirectory Name="src">
|
||||
<File Name="src/main.c"/>
|
||||
</VirtualDirectory>
|
||||
<VirtualDirectory Name="test">
|
||||
<VirtualDirectory Name="include">
|
||||
<File Name="test/include/test_pr1.h"/>
|
||||
<File Name="test/include/test.h"/>
|
||||
<File Name="test/include/test_suite.h"/>
|
||||
</VirtualDirectory>
|
||||
<VirtualDirectory Name="src">
|
||||
<File Name="test/src/test_pr1.c"/>
|
||||
<File Name="test/src/test.c"/>
|
||||
<File Name="test/src/test_suite.c"/>
|
||||
</VirtualDirectory>
|
||||
</VirtualDirectory>
|
||||
<Reconciliation>
|
||||
<Regexes/>
|
||||
<Excludepaths/>
|
||||
<Ignorefiles/>
|
||||
<Extensions>
|
||||
<![CDATA[*.cpp;*.c;*.h;*.hpp;*.xrc;*.wxcp;*.fbp]]>
|
||||
</Extensions>
|
||||
<Topleveldir>/Docencia/PP/20211/PR1/UOC20211</Topleveldir>
|
||||
</Reconciliation>
|
||||
<Description/>
|
||||
<Dependencies/>
|
||||
<Dependencies Name="Debug">
|
||||
<Project Name="UOCContacts"/>
|
||||
</Dependencies>
|
||||
<Dependencies Name="Release">
|
||||
<Project Name="UOCContacts"/>
|
||||
</Dependencies>
|
||||
<Settings Type="Executable">
|
||||
<GlobalSettings>
|
||||
<Compiler Options="" C_Options="" Assembler="">
|
||||
<IncludePath Value="."/>
|
||||
</Compiler>
|
||||
<Linker Options="">
|
||||
<LibraryPath Value="."/>
|
||||
</Linker>
|
||||
<ResourceCompiler Options=""/>
|
||||
</GlobalSettings>
|
||||
<Configuration Name="Debug" CompilerType="MinGW ( TDM-GCC-64 )" DebuggerType="GNU gdb debugger" Type="Executable" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
|
||||
<Compiler Options="-g;-O0;-Wall" C_Options="-g;-O0;-Wall" Assembler="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" PCHFlags="" PCHFlagsPolicy="0">
|
||||
<IncludePath Value="."/>
|
||||
<IncludePath Value="test/include"/>
|
||||
<IncludePath Value="UOCContacts/include"/>
|
||||
</Compiler>
|
||||
<Linker Options="" Required="yes">
|
||||
<LibraryPath Value="./lib"/>
|
||||
<Library Value="libUOCContactsd.a"/>
|
||||
</Linker>
|
||||
<ResourceCompiler Options="" Required="no"/>
|
||||
<General OutputFile="./bin/$(ProjectName)d" IntermediateDirectory="./bin/Debug" Command="$(ProjectName)d" CommandArguments="" UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="./bin" PauseExecWhenProcTerminates="yes" IsGUIProgram="no" IsEnabled="yes"/>
|
||||
<BuildSystem Name="Default"/>
|
||||
<Environment EnvVarSetName="<Use Defaults>" DbgSetName="<Use Defaults>">
|
||||
<![CDATA[]]>
|
||||
</Environment>
|
||||
<Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="" IsExtended="no">
|
||||
<DebuggerSearchPaths/>
|
||||
<PostConnectCommands/>
|
||||
<StartupCommands/>
|
||||
</Debugger>
|
||||
<PreBuild/>
|
||||
<PostBuild/>
|
||||
<CustomBuild Enabled="no">
|
||||
<RebuildCommand/>
|
||||
<CleanCommand/>
|
||||
<BuildCommand/>
|
||||
<PreprocessFileCommand/>
|
||||
<SingleFileCommand/>
|
||||
<MakefileGenerationCommand/>
|
||||
<ThirdPartyToolName>None</ThirdPartyToolName>
|
||||
<WorkingDirectory/>
|
||||
</CustomBuild>
|
||||
<AdditionalRules>
|
||||
<CustomPostBuild/>
|
||||
<CustomPreBuild/>
|
||||
</AdditionalRules>
|
||||
<Completion EnableCpp11="no" EnableCpp14="no">
|
||||
<ClangCmpFlagsC/>
|
||||
<ClangCmpFlags/>
|
||||
<ClangPP/>
|
||||
<SearchPaths/>
|
||||
</Completion>
|
||||
</Configuration>
|
||||
<Configuration Name="Release" CompilerType="MinGW ( TDM-GCC-64 )" DebuggerType="GNU gdb debugger" Type="Executable" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
|
||||
<Compiler Options="-O2;-Wall" C_Options="-O2;-Wall" Assembler="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" PCHFlags="" PCHFlagsPolicy="0">
|
||||
<IncludePath Value="."/>
|
||||
<IncludePath Value="test/include"/>
|
||||
<IncludePath Value="UOCContacts/include"/>
|
||||
<Preprocessor Value="NDEBUG"/>
|
||||
</Compiler>
|
||||
<Linker Options="" Required="yes">
|
||||
<LibraryPath Value="./lib"/>
|
||||
<Library Value="libUOCContacts.a"/>
|
||||
</Linker>
|
||||
<ResourceCompiler Options="" Required="no"/>
|
||||
<General OutputFile="./bin/$(ProjectName)" IntermediateDirectory="./bin/Release" Command="$(ProjectName)" CommandArguments="" UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="./bin" PauseExecWhenProcTerminates="yes" IsGUIProgram="no" IsEnabled="yes"/>
|
||||
<BuildSystem Name="Default"/>
|
||||
<Environment EnvVarSetName="<Use Defaults>" DbgSetName="<Use Defaults>">
|
||||
<![CDATA[]]>
|
||||
</Environment>
|
||||
<Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="" IsExtended="no">
|
||||
<DebuggerSearchPaths/>
|
||||
<PostConnectCommands/>
|
||||
<StartupCommands/>
|
||||
</Debugger>
|
||||
<PreBuild/>
|
||||
<PostBuild/>
|
||||
<CustomBuild Enabled="no">
|
||||
<RebuildCommand/>
|
||||
<CleanCommand/>
|
||||
<BuildCommand/>
|
||||
<PreprocessFileCommand/>
|
||||
<SingleFileCommand/>
|
||||
<MakefileGenerationCommand/>
|
||||
<ThirdPartyToolName>None</ThirdPartyToolName>
|
||||
<WorkingDirectory/>
|
||||
</CustomBuild>
|
||||
<AdditionalRules>
|
||||
<CustomPostBuild/>
|
||||
<CustomPreBuild/>
|
||||
</AdditionalRules>
|
||||
<Completion EnableCpp11="no" EnableCpp14="no">
|
||||
<ClangCmpFlagsC/>
|
||||
<ClangCmpFlags/>
|
||||
<ClangPP/>
|
||||
<SearchPaths/>
|
||||
</Completion>
|
||||
</Configuration>
|
||||
</Settings>
|
||||
</CodeLite_Project>
|
||||
1
UOC20211.txt
Normal file
1
UOC20211.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
./bin/Debug/src_main.c.o ./bin/Debug/test_src_test_suite.c.o ./bin/Debug/test_src_test.c.o ./bin/Debug/test_src_test_pr1.c.o
|
||||
17
UOC20211.workspace
Normal file
17
UOC20211.workspace
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CodeLite_Workspace Name="UOC20211" Database="" Version="10.0.0">
|
||||
<Project Name="UOC20211" Path="UOC20211.project" Active="Yes"/>
|
||||
<Project Name="UOCContacts" Path="UOCContacts/UOCContacts.project"/>
|
||||
<BuildMatrix>
|
||||
<WorkspaceConfiguration Name="Debug" Selected="yes">
|
||||
<Environment/>
|
||||
<Project Name="UOC20211" ConfigName="Debug"/>
|
||||
<Project Name="UOCContacts" ConfigName="Debug"/>
|
||||
</WorkspaceConfiguration>
|
||||
<WorkspaceConfiguration Name="Release" Selected="yes">
|
||||
<Environment/>
|
||||
<Project Name="UOC20211" ConfigName="Release"/>
|
||||
<Project Name="UOCContacts" ConfigName="Release"/>
|
||||
</WorkspaceConfiguration>
|
||||
</BuildMatrix>
|
||||
</CodeLite_Workspace>
|
||||
138
UOCContacts/UOCContacts.mk
Normal file
138
UOCContacts/UOCContacts.mk
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
##
|
||||
## Auto Generated makefile by CodeLite IDE
|
||||
## any manual changes will be erased
|
||||
##
|
||||
## Debug
|
||||
ProjectName :=UOCContacts
|
||||
ConfigurationName :=Debug
|
||||
WorkspacePath :=W:/Docencia/PP/20211/PR1/UOC20211
|
||||
ProjectPath :=W:/Docencia/PP/20211/PR1/UOC20211/UOCContacts
|
||||
IntermediateDirectory :=../bin/Debug
|
||||
OutDir := $(IntermediateDirectory)
|
||||
CurrentFileName :=
|
||||
CurrentFilePath :=
|
||||
CurrentFileFullPath :=
|
||||
User :=xavie
|
||||
Date :=11/10/2021
|
||||
CodeLitePath :="C:/Program Files/CodeLite"
|
||||
LinkerName :=C:/TDM-GCC-64/bin/g++.exe
|
||||
SharedObjectLinkerName :=C:/TDM-GCC-64/bin/g++.exe -shared -fPIC
|
||||
ObjectSuffix :=.o
|
||||
DependSuffix :=.o.d
|
||||
PreprocessSuffix :=.i
|
||||
DebugSwitch :=-g
|
||||
IncludeSwitch :=-I
|
||||
LibrarySwitch :=-l
|
||||
OutputSwitch :=-o
|
||||
LibraryPathSwitch :=-L
|
||||
PreprocessorSwitch :=-D
|
||||
SourceSwitch :=-c
|
||||
OutputFile :=../lib/lib$(ProjectName)d.a
|
||||
Preprocessors :=
|
||||
ObjectSwitch :=-o
|
||||
ArchiveOutputSwitch :=
|
||||
PreprocessOnlySwitch :=-E
|
||||
ObjectsFileList :="UOCContacts.txt"
|
||||
PCHCompileFlags :=
|
||||
MakeDirCommand :=makedir
|
||||
RcCmpOptions :=
|
||||
RcCompilerName :=C:/TDM-GCC-64/bin/windres.exe
|
||||
LinkOptions :=
|
||||
IncludePath := $(IncludeSwitch). $(IncludeSwitch). $(IncludeSwitch)include
|
||||
IncludePCH :=
|
||||
RcIncludePath :=
|
||||
Libs :=
|
||||
ArLibs :=
|
||||
LibPath := $(LibraryPathSwitch).
|
||||
|
||||
##
|
||||
## Common variables
|
||||
## AR, CXX, CC, AS, CXXFLAGS and CFLAGS can be overriden using an environment variables
|
||||
##
|
||||
AR := C:/TDM-GCC-64/bin/ar.exe rcu
|
||||
CXX := C:/TDM-GCC-64/bin/g++.exe
|
||||
CC := C:/TDM-GCC-64/bin/gcc.exe
|
||||
CXXFLAGS := -g $(Preprocessors)
|
||||
CFLAGS := -g $(Preprocessors)
|
||||
ASFLAGS :=
|
||||
AS := C:/TDM-GCC-64/bin/as.exe
|
||||
|
||||
|
||||
##
|
||||
## User defined environment variables
|
||||
##
|
||||
CodeLiteDir:=C:\Program Files\CodeLite
|
||||
Objects0=$(IntermediateDirectory)/src_date.c$(ObjectSuffix) $(IntermediateDirectory)/src_person.c$(ObjectSuffix) $(IntermediateDirectory)/src_csv.c$(ObjectSuffix) $(IntermediateDirectory)/src_api.c$(ObjectSuffix)
|
||||
|
||||
|
||||
|
||||
Objects=$(Objects0)
|
||||
|
||||
##
|
||||
## Main Build Targets
|
||||
##
|
||||
.PHONY: all clean PreBuild PrePreBuild PostBuild MakeIntermediateDirs
|
||||
all: $(IntermediateDirectory) $(OutputFile)
|
||||
|
||||
$(OutputFile): $(Objects)
|
||||
@$(MakeDirCommand) $(@D)
|
||||
@echo "" > $(IntermediateDirectory)/.d
|
||||
@echo $(Objects0) > $(ObjectsFileList)
|
||||
$(AR) $(ArchiveOutputSwitch)$(OutputFile) @$(ObjectsFileList) $(ArLibs)
|
||||
@$(MakeDirCommand) "W:\Docencia\PP\20211\PR1\UOC20211/.build-debug"
|
||||
@echo rebuilt > "W:\Docencia\PP\20211\PR1\UOC20211/.build-debug/UOCContacts"
|
||||
|
||||
MakeIntermediateDirs:
|
||||
@$(MakeDirCommand) "../bin/Debug"
|
||||
|
||||
|
||||
../bin/Debug:
|
||||
@$(MakeDirCommand) "../bin/Debug"
|
||||
|
||||
PreBuild:
|
||||
|
||||
|
||||
##
|
||||
## Objects
|
||||
##
|
||||
$(IntermediateDirectory)/src_date.c$(ObjectSuffix): src/date.c $(IntermediateDirectory)/src_date.c$(DependSuffix)
|
||||
$(CC) $(SourceSwitch) "W:/Docencia/PP/20211/PR1/UOC20211/UOCContacts/src/date.c" $(CFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/src_date.c$(ObjectSuffix) $(IncludePath)
|
||||
$(IntermediateDirectory)/src_date.c$(DependSuffix): src/date.c
|
||||
@$(CC) $(CFLAGS) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/src_date.c$(ObjectSuffix) -MF$(IntermediateDirectory)/src_date.c$(DependSuffix) -MM src/date.c
|
||||
|
||||
$(IntermediateDirectory)/src_date.c$(PreprocessSuffix): src/date.c
|
||||
$(CC) $(CFLAGS) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/src_date.c$(PreprocessSuffix) src/date.c
|
||||
|
||||
$(IntermediateDirectory)/src_person.c$(ObjectSuffix): src/person.c $(IntermediateDirectory)/src_person.c$(DependSuffix)
|
||||
$(CC) $(SourceSwitch) "W:/Docencia/PP/20211/PR1/UOC20211/UOCContacts/src/person.c" $(CFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/src_person.c$(ObjectSuffix) $(IncludePath)
|
||||
$(IntermediateDirectory)/src_person.c$(DependSuffix): src/person.c
|
||||
@$(CC) $(CFLAGS) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/src_person.c$(ObjectSuffix) -MF$(IntermediateDirectory)/src_person.c$(DependSuffix) -MM src/person.c
|
||||
|
||||
$(IntermediateDirectory)/src_person.c$(PreprocessSuffix): src/person.c
|
||||
$(CC) $(CFLAGS) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/src_person.c$(PreprocessSuffix) src/person.c
|
||||
|
||||
$(IntermediateDirectory)/src_csv.c$(ObjectSuffix): src/csv.c $(IntermediateDirectory)/src_csv.c$(DependSuffix)
|
||||
$(CC) $(SourceSwitch) "W:/Docencia/PP/20211/PR1/UOC20211/UOCContacts/src/csv.c" $(CFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/src_csv.c$(ObjectSuffix) $(IncludePath)
|
||||
$(IntermediateDirectory)/src_csv.c$(DependSuffix): src/csv.c
|
||||
@$(CC) $(CFLAGS) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/src_csv.c$(ObjectSuffix) -MF$(IntermediateDirectory)/src_csv.c$(DependSuffix) -MM src/csv.c
|
||||
|
||||
$(IntermediateDirectory)/src_csv.c$(PreprocessSuffix): src/csv.c
|
||||
$(CC) $(CFLAGS) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/src_csv.c$(PreprocessSuffix) src/csv.c
|
||||
|
||||
$(IntermediateDirectory)/src_api.c$(ObjectSuffix): src/api.c $(IntermediateDirectory)/src_api.c$(DependSuffix)
|
||||
$(CC) $(SourceSwitch) "W:/Docencia/PP/20211/PR1/UOC20211/UOCContacts/src/api.c" $(CFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/src_api.c$(ObjectSuffix) $(IncludePath)
|
||||
$(IntermediateDirectory)/src_api.c$(DependSuffix): src/api.c
|
||||
@$(CC) $(CFLAGS) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/src_api.c$(ObjectSuffix) -MF$(IntermediateDirectory)/src_api.c$(DependSuffix) -MM src/api.c
|
||||
|
||||
$(IntermediateDirectory)/src_api.c$(PreprocessSuffix): src/api.c
|
||||
$(CC) $(CFLAGS) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/src_api.c$(PreprocessSuffix) src/api.c
|
||||
|
||||
|
||||
-include $(IntermediateDirectory)/*$(DependSuffix)
|
||||
##
|
||||
## Clean
|
||||
##
|
||||
clean:
|
||||
$(RM) -r ../bin/Debug/
|
||||
|
||||
|
||||
122
UOCContacts/UOCContacts.project
Normal file
122
UOCContacts/UOCContacts.project
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CodeLite_Project Name="UOCContacts" Version="10.0.0" InternalType="Library">
|
||||
<Plugins>
|
||||
<Plugin Name="qmake">
|
||||
<![CDATA[00020001N0005Debug0000000000000001N0007Release000000000000]]>
|
||||
</Plugin>
|
||||
</Plugins>
|
||||
<Reconciliation>
|
||||
<Regexes/>
|
||||
<Excludepaths/>
|
||||
<Ignorefiles/>
|
||||
<Extensions>
|
||||
<![CDATA[*.cpp;*.c;*.h;*.hpp;*.xrc;*.wxcp;*.fbp]]>
|
||||
</Extensions>
|
||||
<Topleveldir>/Docencia/PP/20211/PR1/UOC20211/UOCContacts</Topleveldir>
|
||||
</Reconciliation>
|
||||
<Description/>
|
||||
<Dependencies/>
|
||||
<VirtualDirectory Name="src">
|
||||
<File Name="src/date.c"/>
|
||||
<File Name="src/person.c"/>
|
||||
<File Name="src/csv.c"/>
|
||||
<File Name="src/api.c"/>
|
||||
</VirtualDirectory>
|
||||
<VirtualDirectory Name="include">
|
||||
<File Name="include/date.h"/>
|
||||
<File Name="include/person.h"/>
|
||||
<File Name="include/csv.h"/>
|
||||
<File Name="include/error.h"/>
|
||||
<File Name="include/api.h"/>
|
||||
</VirtualDirectory>
|
||||
<Settings Type="Static Library">
|
||||
<GlobalSettings>
|
||||
<Compiler Options="" C_Options="" Assembler="">
|
||||
<IncludePath Value="."/>
|
||||
</Compiler>
|
||||
<Linker Options="">
|
||||
<LibraryPath Value="."/>
|
||||
</Linker>
|
||||
<ResourceCompiler Options=""/>
|
||||
</GlobalSettings>
|
||||
<Configuration Name="Debug" CompilerType="MinGW ( TDM-GCC-64 )" DebuggerType="GNU gdb debugger" Type="Static Library" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
|
||||
<Compiler Options="-g" C_Options="-g" Assembler="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" PCHFlags="" PCHFlagsPolicy="0">
|
||||
<IncludePath Value="."/>
|
||||
<IncludePath Value="include"/>
|
||||
</Compiler>
|
||||
<Linker Options="" Required="yes"/>
|
||||
<ResourceCompiler Options="" Required="no"/>
|
||||
<General OutputFile="../lib/lib$(ProjectName)d.a" IntermediateDirectory="../bin/Debug" Command="" CommandArguments="" UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="" PauseExecWhenProcTerminates="yes" IsGUIProgram="no" IsEnabled="yes"/>
|
||||
<BuildSystem Name="Default"/>
|
||||
<Environment EnvVarSetName="<Use Defaults>" DbgSetName="<Use Defaults>">
|
||||
<![CDATA[]]>
|
||||
</Environment>
|
||||
<Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="" IsExtended="no">
|
||||
<DebuggerSearchPaths/>
|
||||
<PostConnectCommands/>
|
||||
<StartupCommands/>
|
||||
</Debugger>
|
||||
<PreBuild/>
|
||||
<PostBuild/>
|
||||
<CustomBuild Enabled="no">
|
||||
<RebuildCommand/>
|
||||
<CleanCommand/>
|
||||
<BuildCommand/>
|
||||
<PreprocessFileCommand/>
|
||||
<SingleFileCommand/>
|
||||
<MakefileGenerationCommand/>
|
||||
<ThirdPartyToolName/>
|
||||
<WorkingDirectory/>
|
||||
</CustomBuild>
|
||||
<AdditionalRules>
|
||||
<CustomPostBuild/>
|
||||
<CustomPreBuild/>
|
||||
</AdditionalRules>
|
||||
<Completion EnableCpp11="no" EnableCpp14="no">
|
||||
<ClangCmpFlagsC/>
|
||||
<ClangCmpFlags/>
|
||||
<ClangPP/>
|
||||
<SearchPaths/>
|
||||
</Completion>
|
||||
</Configuration>
|
||||
<Configuration Name="Release" CompilerType="MinGW ( TDM-GCC-64 )" DebuggerType="GNU gdb debugger" Type="Static Library" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
|
||||
<Compiler Options="" C_Options="" Assembler="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" PCHFlags="" PCHFlagsPolicy="0">
|
||||
<IncludePath Value="."/>
|
||||
</Compiler>
|
||||
<Linker Options="" Required="yes"/>
|
||||
<ResourceCompiler Options="" Required="no"/>
|
||||
<General OutputFile="../lib/lib$(ProjectName).a" IntermediateDirectory="../bin/Release" Command="" CommandArguments="" UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="" PauseExecWhenProcTerminates="yes" IsGUIProgram="no" IsEnabled="yes"/>
|
||||
<BuildSystem Name="Default"/>
|
||||
<Environment EnvVarSetName="<Use Defaults>" DbgSetName="<Use Defaults>">
|
||||
<![CDATA[]]>
|
||||
</Environment>
|
||||
<Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="" IsExtended="no">
|
||||
<DebuggerSearchPaths/>
|
||||
<PostConnectCommands/>
|
||||
<StartupCommands/>
|
||||
</Debugger>
|
||||
<PreBuild/>
|
||||
<PostBuild/>
|
||||
<CustomBuild Enabled="no">
|
||||
<RebuildCommand/>
|
||||
<CleanCommand/>
|
||||
<BuildCommand/>
|
||||
<PreprocessFileCommand/>
|
||||
<SingleFileCommand/>
|
||||
<MakefileGenerationCommand/>
|
||||
<ThirdPartyToolName/>
|
||||
<WorkingDirectory/>
|
||||
</CustomBuild>
|
||||
<AdditionalRules>
|
||||
<CustomPostBuild/>
|
||||
<CustomPreBuild/>
|
||||
</AdditionalRules>
|
||||
<Completion EnableCpp11="no" EnableCpp14="no">
|
||||
<ClangCmpFlagsC/>
|
||||
<ClangCmpFlags/>
|
||||
<ClangPP/>
|
||||
<SearchPaths/>
|
||||
</Completion>
|
||||
</Configuration>
|
||||
</Settings>
|
||||
</CodeLite_Project>
|
||||
1
UOCContacts/UOCContacts.txt
Normal file
1
UOCContacts/UOCContacts.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
../bin/Debug/src_date.c.o ../bin/Debug/src_person.c.o ../bin/Debug/src_csv.c.o ../bin/Debug/src_api.c.o
|
||||
40
UOCContacts/include/api.h
Normal file
40
UOCContacts/include/api.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef __UOCCONTACTS_API__H
|
||||
#define __UOCCONTACTS_API__H
|
||||
#include <stdbool.h>
|
||||
#include "error.h"
|
||||
#include "csv.h"
|
||||
|
||||
// Type that stores all the application data
|
||||
typedef struct _ApiData {
|
||||
//////////////////////////////////
|
||||
// Ex PR1 2:
|
||||
/////////////////////////////////
|
||||
|
||||
} tApiData;
|
||||
|
||||
// Get the API version information
|
||||
const char* api_version();
|
||||
|
||||
// Load data from a CSV file. If reset is true, remove previous data
|
||||
tApiError api_loadData(tApiData* data, const char* filename, bool reset);
|
||||
|
||||
// Add a new entry
|
||||
tApiError api_addDataEntry(tApiData* data, tCSVEntry entry);
|
||||
|
||||
// Free all used memory
|
||||
tApiError api_freeData(tApiData* data);
|
||||
|
||||
// Initialize the data structure
|
||||
tApiError api_initData(tApiData* data);
|
||||
|
||||
// Get person data
|
||||
tApiError api_findPerson(tApiData* data, const char* document, tCSVEntry* person);
|
||||
|
||||
// Get all geolocation data for a given person
|
||||
tApiError api_getPersonGeolocation(tApiData* data, const char* document, tCSVData* geodata);
|
||||
|
||||
// Remove a person
|
||||
tApiError api_removePerson(tApiData* data, const char* document);
|
||||
|
||||
|
||||
#endif // __UOCCONTACTS_API__H
|
||||
72
UOCContacts/include/csv.h
Normal file
72
UOCContacts/include/csv.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#ifndef __CSV_H__
|
||||
#define __CSV_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#define CSV_SEPARATOR_CHAR ;
|
||||
|
||||
// Store one entry from a CSV file
|
||||
typedef struct _tCSVEntry {
|
||||
int numFields;
|
||||
char* type;
|
||||
char** fields;
|
||||
} tCSVEntry;
|
||||
|
||||
// Store the content of a CSV file
|
||||
typedef struct _tCSVData {
|
||||
tCSVEntry *entries;
|
||||
int count;
|
||||
bool isValid;
|
||||
} tCSVData;
|
||||
|
||||
// Initialize the tCSVData structure
|
||||
void csv_init(tCSVData* data);
|
||||
|
||||
// Initialize the tCSVEntry structure
|
||||
void csv_initEntry(tCSVEntry* entry);
|
||||
|
||||
// Parse the contents of a CSV file
|
||||
void csv_parse(tCSVData* data, const char* input, const char* type);
|
||||
|
||||
// Add a new entry to the CSV Data
|
||||
void csv_addStrEntry(tCSVData* data, const char* entry, const char* type);
|
||||
|
||||
// Print the content of the CSV data structure
|
||||
void csv_print(tCSVData data);
|
||||
|
||||
// Print the content of the CSV entry structure
|
||||
void csv_printEntry(tCSVEntry entry);
|
||||
|
||||
// Parse the contents of a CSV line "f1;f2;f3" => field_0 = f1, field_1 = f2, field_2 = f3
|
||||
void csv_parseEntry(tCSVEntry* entry, const char* input, const char* type);
|
||||
|
||||
// Get the number of entries
|
||||
bool csv_isValid(tCSVData data);
|
||||
|
||||
// Remove all data from structure
|
||||
void csv_free(tCSVData* data);
|
||||
|
||||
// Remove all data from structure
|
||||
void csv_freeEntry(tCSVEntry* entry);
|
||||
|
||||
// Get the number of entries
|
||||
int csv_numEntries(tCSVData data);
|
||||
|
||||
// Get the type of information contained in the entry
|
||||
const char* csv_getType(tCSVEntry* entry);
|
||||
|
||||
// Get an entry from the CSV data
|
||||
tCSVEntry* csv_getEntry(tCSVData data, int position);
|
||||
|
||||
// Get the number of fields for a given entry
|
||||
int csv_numFields(tCSVEntry entry);
|
||||
|
||||
// Get a field from the given entry as integer
|
||||
int csv_getAsInteger(tCSVEntry entry, int position);
|
||||
|
||||
// Get a field from the given entry as string. The value is copied to the provided buffer with provided maximum length
|
||||
void csv_getAsString(tCSVEntry entry, int position, char* buffer, int length);
|
||||
|
||||
// Get a field from the given entry as integer
|
||||
float csv_getAsReal(tCSVEntry entry, int position);
|
||||
|
||||
#endif
|
||||
28
UOCContacts/include/date.h
Normal file
28
UOCContacts/include/date.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef __DATE_H__
|
||||
#define __DATE_H__
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct _tDate {
|
||||
int day;
|
||||
int month;
|
||||
int year;
|
||||
} tDate;
|
||||
|
||||
typedef struct _tTime {
|
||||
int hour;
|
||||
int minutes;
|
||||
} tTime;
|
||||
|
||||
typedef struct _tDateTime {
|
||||
tDate date;
|
||||
tTime time;
|
||||
} tDateTime;
|
||||
|
||||
|
||||
// Parse a tDateTime from string information
|
||||
void dateTime_parse(tDateTime* dateTime, const char* date, const char* time);
|
||||
|
||||
// Compare two tDateTime structures and return true if they contain the same value or false otherwise.
|
||||
bool dateTime_cmp(tDateTime dateTime1, tDateTime dateTime2);
|
||||
|
||||
#endif // __DATE_H__
|
||||
19
UOCContacts/include/error.h
Normal file
19
UOCContacts/include/error.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef __UOCCONTACTS_ERROR__H
|
||||
#define __UOCCONTACTS_ERROR__H
|
||||
|
||||
// Define error codes
|
||||
enum _tApiError
|
||||
{
|
||||
E_SUCCESS = 0, // No error
|
||||
E_NOT_IMPLEMENTED = -1, // Called method is not implemented
|
||||
E_FILE_NOT_FOUND = -2, // File not found
|
||||
E_PERSON_NOT_FOUND = -3, // Person not found
|
||||
E_INVALID_ENTRY_TYPE = -4, // Invalid entry type
|
||||
E_INVALID_ENTRY_FORMAT = -5, // Invalid entry format
|
||||
E_DUPLICATED_ENTRY = -6, // Duplicated entry
|
||||
};
|
||||
|
||||
// Define an error type
|
||||
typedef enum _tApiError tApiError;
|
||||
|
||||
#endif // __UOCCONTACTS_ERRORS__H
|
||||
48
UOCContacts/include/person.h
Normal file
48
UOCContacts/include/person.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#ifndef __PERSON_H__
|
||||
#define __PERSON_H__
|
||||
#include "csv.h"
|
||||
#include "date.h"
|
||||
|
||||
typedef struct _tPerson {
|
||||
char* document;
|
||||
char* name;
|
||||
char* surname;
|
||||
char* cp;
|
||||
char* email;
|
||||
char* address;
|
||||
tDate birthday;
|
||||
} tPerson;
|
||||
|
||||
typedef struct _tPopulation {
|
||||
tPerson* elems;
|
||||
int count;
|
||||
} tPopulation;
|
||||
|
||||
// Initialize the population data
|
||||
void population_init(tPopulation* data);
|
||||
|
||||
// Remove the data from a person
|
||||
void person_free(tPerson* data);
|
||||
|
||||
// Remove the data from all persons
|
||||
void population_free(tPopulation* data);
|
||||
|
||||
// Parse input from CSVEntry
|
||||
void person_parse(tPerson* data, tCSVEntry entry);
|
||||
|
||||
// Add a new person
|
||||
void population_add(tPopulation* data, tPerson person);
|
||||
|
||||
// Remove a person
|
||||
void population_del(tPopulation* data, const char *document);
|
||||
|
||||
// Return the position of a person with provided document. -1 if it does not exist
|
||||
int population_find(tPopulation data, const char* document);
|
||||
|
||||
// Print the person data
|
||||
void population_print(tPopulation data);
|
||||
|
||||
// Copy the data from the source to destination
|
||||
void person_cpy(tPerson* destination, tPerson source);
|
||||
|
||||
#endif
|
||||
114
UOCContacts/src/api.c
Normal file
114
UOCContacts/src/api.c
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "csv.h"
|
||||
#include "api.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define FILE_READ_BUFFER_SIZE 2048
|
||||
|
||||
// Get the API version information
|
||||
const char* api_version() {
|
||||
return "UOC PP 20211";
|
||||
}
|
||||
|
||||
// Load data from a CSV file. If reset is true, remove previous data
|
||||
tApiError api_loadData(tApiData* data, const char* filename, bool reset) {
|
||||
tApiError error;
|
||||
FILE *fin;
|
||||
char buffer[FILE_READ_BUFFER_SIZE];
|
||||
tCSVEntry entry;
|
||||
|
||||
// Check input data
|
||||
assert( data != NULL );
|
||||
assert(filename != NULL);
|
||||
|
||||
// Reset current data
|
||||
if (reset) {
|
||||
// Remove previous information
|
||||
error = api_freeData(data);
|
||||
if (error != E_SUCCESS) {
|
||||
return error;
|
||||
}
|
||||
|
||||
// Initialize the data
|
||||
error = api_initData(data);
|
||||
if (error != E_SUCCESS) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
// Open the input file
|
||||
fin = fopen(filename, "r");
|
||||
if (fin == NULL) {
|
||||
return E_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Read file line by line
|
||||
while (fgets(buffer, FILE_READ_BUFFER_SIZE, fin)) {
|
||||
// Remove new line character
|
||||
buffer[strcspn(buffer, "\n\r")] = '\0';
|
||||
|
||||
csv_initEntry(&entry);
|
||||
csv_parseEntry(&entry, buffer, NULL);
|
||||
// Add this new entry to the api Data
|
||||
error = api_addDataEntry(data, entry);
|
||||
if (error != E_SUCCESS) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fin);
|
||||
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
// Add a new entry
|
||||
tApiError api_addDataEntry(tApiData* data, tCSVEntry entry) {
|
||||
|
||||
//////////////////////////////////
|
||||
// Ex PR1 2
|
||||
/////////////////////////////////
|
||||
return E_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Free all used memory
|
||||
tApiError api_freeData(tApiData* data) {
|
||||
//////////////////////////////////
|
||||
// Ex PR1 2:
|
||||
/////////////////////////////////
|
||||
return E_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Initialize the data structure
|
||||
tApiError api_initData(tApiData* data) {
|
||||
|
||||
//////////////////////////////////
|
||||
// Ex PR1 2:
|
||||
/////////////////////////////////
|
||||
return E_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Get person data
|
||||
tApiError api_findPerson(tApiData* data, const char* document, tCSVEntry* person) {
|
||||
//////////////////////////////////
|
||||
// Ex PR1 3
|
||||
/////////////////////////////////
|
||||
return E_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Get all geolocation data for a given person
|
||||
tApiError api_getPersonGeolocation(tApiData* data, const char* document, tCSVData* geodata) {
|
||||
//////////////////////////////////
|
||||
// Ex PR1 3
|
||||
/////////////////////////////////
|
||||
return E_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Remove a person
|
||||
tApiError api_removePerson(tApiData* data, const char* document) {
|
||||
//////////////////////////////////
|
||||
// Ex PR1 3
|
||||
/////////////////////////////////
|
||||
return E_NOT_IMPLEMENTED;
|
||||
}
|
||||
232
UOCContacts/src/csv.c
Normal file
232
UOCContacts/src/csv.c
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
#include "csv.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
// Initialize the tCSVData structure
|
||||
void csv_init(tCSVData* data) {
|
||||
data->count = 0;
|
||||
data->isValid = false;
|
||||
data->entries = NULL;
|
||||
}
|
||||
|
||||
// Initialize the tCSVEntry structure
|
||||
void csv_initEntry(tCSVEntry* entry) {
|
||||
entry->numFields = 0;
|
||||
entry->fields = NULL;
|
||||
entry->type = NULL;
|
||||
}
|
||||
|
||||
// Add a new entry to the CSV Data
|
||||
void csv_addStrEntry(tCSVData* data, const char* entry, const char* type) {
|
||||
assert( data != NULL );
|
||||
assert( entry != NULL );
|
||||
data->count++;
|
||||
if (data->count == 1) {
|
||||
data->entries = (tCSVEntry*) malloc(sizeof(tCSVEntry));
|
||||
} else {
|
||||
data->entries = (tCSVEntry*) realloc(data->entries, data->count * sizeof(tCSVEntry));
|
||||
}
|
||||
csv_initEntry(&(data->entries[data->count-1]));
|
||||
csv_parseEntry(&(data->entries[data->count-1]), entry, type);
|
||||
}
|
||||
|
||||
// Parse the contents of a CSV file
|
||||
void csv_parse(tCSVData* data, const char* input, const char* type) {
|
||||
const char *pStart, *pEnd;
|
||||
char *line;
|
||||
int len;
|
||||
|
||||
assert(data->count == 0);
|
||||
assert(data->entries == NULL);
|
||||
assert(!data->isValid);
|
||||
|
||||
pStart = input;
|
||||
pEnd = strchr(pStart, '\n');
|
||||
while(pEnd != NULL && pEnd != pStart) {
|
||||
len = pEnd - pStart + 1;
|
||||
line = (char*) malloc(len * sizeof(char));
|
||||
memset(line, 0, len * sizeof(char));
|
||||
strncpy(line, pStart, pEnd - pStart);
|
||||
// Add the new entry line
|
||||
csv_addStrEntry(data, line, type);
|
||||
free(line);
|
||||
pStart = pEnd + 1;
|
||||
pEnd = strchr(pStart, '\n');
|
||||
}
|
||||
pEnd = strchr(pStart, '\0');
|
||||
if (pEnd != NULL && pEnd != pStart) {
|
||||
len = pEnd - pStart + 1;
|
||||
line = (char*) malloc(len * sizeof(char));
|
||||
memset(line, 0, len * sizeof(char));
|
||||
strncpy(line, pStart, pEnd - pStart);
|
||||
data->count++;
|
||||
if (data->count == 1) {
|
||||
data->entries = (tCSVEntry*) malloc(sizeof(tCSVEntry));
|
||||
} else {
|
||||
data->entries = (tCSVEntry*) realloc(data->entries, data->count * sizeof(tCSVEntry));
|
||||
}
|
||||
csv_initEntry(&(data->entries[data->count-1]));
|
||||
csv_parseEntry(&(data->entries[data->count-1]), line, type);
|
||||
free(line);
|
||||
}
|
||||
data->isValid = true;
|
||||
}
|
||||
|
||||
// Print the content of the CSV data structure
|
||||
void csv_print(tCSVData data) {
|
||||
int i;
|
||||
tCSVEntry* entry = NULL;
|
||||
|
||||
for (i = 0; i < csv_numEntries(data); i++) {
|
||||
entry = csv_getEntry(data, i);
|
||||
printf("===============\n");
|
||||
printf("Entry %d: %s\n", i, entry->type);
|
||||
printf("===============\n");
|
||||
csv_printEntry(*entry);
|
||||
printf("===============\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Print the content of the CSV entry structure
|
||||
void csv_printEntry(tCSVEntry entry) {
|
||||
int i;
|
||||
char buffer[512];
|
||||
printf("\tNum Fields: %d\n", csv_numFields(entry));
|
||||
for (i = 0; i < csv_numFields(entry); i++) {
|
||||
csv_getAsString(entry, i, buffer, 512);
|
||||
printf("\tField %d: %s\n", i, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the contents of a CSV line
|
||||
void csv_parseEntry(tCSVEntry* entry, const char* input, const char* type) {
|
||||
const char *pStart, *pEnd;
|
||||
int len;
|
||||
bool readType = true;
|
||||
|
||||
assert(entry->numFields == 0);
|
||||
assert(entry->fields == NULL);
|
||||
|
||||
// If the type of the entry is not provided, use the first field
|
||||
if(type != NULL) {
|
||||
len = strlen(type) + 1;
|
||||
entry->type = (char*) malloc(len * sizeof(char));
|
||||
memset(entry->type, 0, len * sizeof(char));
|
||||
strncpy(entry->type, type, len);
|
||||
readType = false;
|
||||
}
|
||||
pStart = input;
|
||||
pEnd = strchr(pStart, ';');
|
||||
while(pEnd != NULL && pEnd != pStart) {
|
||||
// Get the length of the field
|
||||
len = pEnd - pStart + 1;
|
||||
|
||||
if(readType) {
|
||||
entry->type = (char*) malloc(len * sizeof(char));
|
||||
memset(entry->type, 0, len * sizeof(char));
|
||||
strncpy(entry->type, pStart, pEnd - pStart);
|
||||
readType = false;
|
||||
} else {
|
||||
entry->numFields++;
|
||||
if (entry->numFields == 1) {
|
||||
entry->fields = (char**) malloc(sizeof(char*));
|
||||
} else {
|
||||
entry->fields = (char**) realloc(entry->fields, entry->numFields * sizeof(char*));
|
||||
}
|
||||
entry->fields[entry->numFields - 1] = (char*) malloc(len * sizeof(char));
|
||||
memset(entry->fields[entry->numFields - 1], 0, len * sizeof(char));
|
||||
strncpy(entry->fields[entry->numFields - 1], pStart, pEnd - pStart);
|
||||
}
|
||||
|
||||
pStart = pEnd + 1;
|
||||
pEnd = strchr(pStart, ';');
|
||||
}
|
||||
pEnd = strchr(pStart, '\0');
|
||||
if (pEnd != NULL && pEnd != pStart) {
|
||||
|
||||
assert(!readType);
|
||||
|
||||
entry->numFields++;
|
||||
if (entry->numFields == 1) {
|
||||
entry->fields = (char**) malloc(sizeof(char*));
|
||||
} else {
|
||||
entry->fields = (char**) realloc(entry->fields, entry->numFields * sizeof(char*));
|
||||
}
|
||||
len = pEnd - pStart + 1;
|
||||
entry->fields[entry->numFields - 1] = (char*) malloc(len * sizeof(char));
|
||||
memset(entry->fields[entry->numFields - 1], 0, len * sizeof(char));
|
||||
strncpy(entry->fields[entry->numFields - 1], pStart, pEnd - pStart);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the number of entries
|
||||
bool csv_isValid(tCSVData data) {
|
||||
return data.isValid;
|
||||
}
|
||||
|
||||
// Remove all data from structure
|
||||
void csv_free(tCSVData* data) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < data->count; i++) {
|
||||
csv_freeEntry(&(data->entries[i]));
|
||||
}
|
||||
free(data->entries);
|
||||
csv_init(data);
|
||||
}
|
||||
|
||||
// Remove all data from structure
|
||||
void csv_freeEntry(tCSVEntry* entry) {
|
||||
int i;
|
||||
|
||||
if(entry->fields != NULL) {
|
||||
for(i = 0; i < entry->numFields; i++) {
|
||||
free(entry->fields[i]);
|
||||
entry->fields[i] = NULL;
|
||||
}
|
||||
|
||||
free(entry->fields);
|
||||
}
|
||||
if(entry->type != NULL) {
|
||||
free(entry->type);
|
||||
}
|
||||
csv_initEntry(entry);
|
||||
}
|
||||
|
||||
// Get the number of entries
|
||||
int csv_numEntries(tCSVData data) {
|
||||
return data.count;
|
||||
}
|
||||
|
||||
// Get the type of information contained in the entry
|
||||
const char* csv_getType(tCSVEntry* entry) {
|
||||
return (const char*)entry->type;
|
||||
}
|
||||
|
||||
// Get an entry from the CSV data
|
||||
tCSVEntry* csv_getEntry(tCSVData data, int position) {
|
||||
return &(data.entries[position]);
|
||||
}
|
||||
|
||||
// Get the number of fields for a given entry
|
||||
int csv_numFields(tCSVEntry entry) {
|
||||
return entry.numFields;
|
||||
}
|
||||
|
||||
// Get a field from the given entry as integer
|
||||
int csv_getAsInteger(tCSVEntry entry, int position) {
|
||||
return atoi(entry.fields[position]);
|
||||
}
|
||||
|
||||
// Get a field from the given entry as string
|
||||
void csv_getAsString(tCSVEntry entry, int position, char* buffer, int length) {
|
||||
memset(buffer, 0, length);
|
||||
strncpy(buffer, entry.fields[position], length - 1);
|
||||
}
|
||||
|
||||
// Get a field from the given entry as integer
|
||||
float csv_getAsReal(tCSVEntry entry, int position) {
|
||||
return atof(entry.fields[position]);
|
||||
}
|
||||
34
UOCContacts/src/date.c
Normal file
34
UOCContacts/src/date.c
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "date.h"
|
||||
|
||||
// Parse a tDateTime from string information
|
||||
void dateTime_parse(tDateTime* dateTime, const char* date, const char* time) {
|
||||
// Check output data
|
||||
assert(dateTime != NULL);
|
||||
|
||||
// Check input date
|
||||
assert(date != NULL);
|
||||
assert(strlen(date) == 10);
|
||||
|
||||
// Check input time
|
||||
assert(time != NULL);
|
||||
assert(strlen(time) == 5);
|
||||
|
||||
// Parse the input date
|
||||
sscanf(date, "%d/%d/%d", &(dateTime->date.day), &(dateTime->date.month), &(dateTime->date.year));
|
||||
|
||||
// Parse the input time
|
||||
sscanf(time, "%d:%d", &(dateTime->time.hour), &(dateTime->time.minutes));
|
||||
}
|
||||
|
||||
// Compare two tDateTime structures and return true if they contain the same value or false otherwise.
|
||||
bool dateTime_cmp(tDateTime dateTime1, tDateTime dateTime2) {
|
||||
if (dateTime1.date.day != dateTime2.date.day || dateTime1.date.month != dateTime2.date.month || dateTime1.date.year != dateTime2.date.year) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return dateTime1.time.hour == dateTime2.time.hour && dateTime1.time.minutes == dateTime2.time.minutes;
|
||||
}
|
||||
241
UOCContacts/src/person.c
Normal file
241
UOCContacts/src/person.c
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "person.h"
|
||||
|
||||
|
||||
// Initialize the population data
|
||||
void population_init(tPopulation* data) {
|
||||
// Check input/output data
|
||||
assert(data != NULL);
|
||||
|
||||
data->elems = NULL;
|
||||
data->count = 0;
|
||||
}
|
||||
|
||||
// Remove the data from a person
|
||||
void person_free(tPerson* data) {
|
||||
// Check input data
|
||||
assert(data != NULL);
|
||||
|
||||
// Release document data
|
||||
if(data->document != NULL) free(data->document);
|
||||
data->document = NULL;
|
||||
|
||||
// Release name data
|
||||
if(data->name != NULL) free(data->name);
|
||||
data->name = NULL;
|
||||
|
||||
// Release surname data
|
||||
if(data->surname != NULL) free(data->surname);
|
||||
data->surname = NULL;
|
||||
|
||||
// Release email data
|
||||
if(data->email != NULL) free(data->email);
|
||||
data->email = NULL;
|
||||
|
||||
// Release address data
|
||||
if(data->address != NULL) free(data->address);
|
||||
data->address = NULL;
|
||||
|
||||
// Release cp data
|
||||
if(data->cp != NULL) free(data->cp);
|
||||
data->cp = NULL;
|
||||
}
|
||||
|
||||
// Remove the data from all persons
|
||||
void population_free(tPopulation* data) {
|
||||
int i;
|
||||
|
||||
// Check input data
|
||||
assert(data != NULL);
|
||||
|
||||
// Remove contents
|
||||
for(i = 0; i < data->count; i++) {
|
||||
person_free(&(data->elems[i]));
|
||||
}
|
||||
|
||||
// Release memory
|
||||
if (data->count > 0) {
|
||||
free(data->elems);
|
||||
data->elems = NULL;
|
||||
data->count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Parse input from CSVEntry
|
||||
void person_parse(tPerson* data, tCSVEntry entry) {
|
||||
// Check input data
|
||||
assert(data != NULL);
|
||||
|
||||
// Check entry fields
|
||||
assert(csv_numFields(entry) == 7);
|
||||
|
||||
// Copy identity document data
|
||||
data->document = (char*) malloc((strlen(entry.fields[0]) + 1) * sizeof(char));
|
||||
assert(data->document != NULL);
|
||||
memset(data->document, 0, (strlen(entry.fields[0]) + 1) * sizeof(char));
|
||||
csv_getAsString(entry, 0, data->document, strlen(entry.fields[0]) + 1);
|
||||
|
||||
// Copy name data
|
||||
data->name = (char*) malloc((strlen(entry.fields[1]) + 1) * sizeof(char));
|
||||
assert(data->name != NULL);
|
||||
memset(data->name, 0, (strlen(entry.fields[1]) + 1) * sizeof(char));
|
||||
csv_getAsString(entry, 1, data->name, strlen(entry.fields[1]) + 1);
|
||||
|
||||
// Copy surname data
|
||||
data->surname = (char*) malloc((strlen(entry.fields[2]) + 1) * sizeof(char));
|
||||
assert(data->surname != NULL);
|
||||
memset(data->surname, 0, (strlen(entry.fields[2]) + 1) * sizeof(char));
|
||||
csv_getAsString(entry, 2, data->surname, strlen(entry.fields[2]) + 1);
|
||||
|
||||
// Copy email data
|
||||
data->email = (char*) malloc((strlen(entry.fields[3]) + 1) * sizeof(char));
|
||||
assert(data->email != NULL);
|
||||
memset(data->email, 0, (strlen(entry.fields[3]) + 1) * sizeof(char));
|
||||
csv_getAsString(entry, 3, data->email, strlen(entry.fields[3]) + 1);
|
||||
|
||||
// Copy address data
|
||||
data->address = (char*) malloc((strlen(entry.fields[4]) + 1) * sizeof(char));
|
||||
assert(data->address != NULL);
|
||||
memset(data->address, 0, (strlen(entry.fields[4]) + 1) * sizeof(char));
|
||||
csv_getAsString(entry, 4, data->address, strlen(entry.fields[4]) + 1);
|
||||
|
||||
// Copy cp data
|
||||
data->cp = (char*) malloc((strlen(entry.fields[5]) + 1) * sizeof(char));
|
||||
assert(data->cp != NULL);
|
||||
memset(data->cp, 0, (strlen(entry.fields[5]) + 1) * sizeof(char));
|
||||
csv_getAsString(entry, 5, data->cp, strlen(entry.fields[5]) + 1);
|
||||
|
||||
// Check birthday lenght
|
||||
assert(strlen(entry.fields[6]) == 10);
|
||||
// Parse the birthday date
|
||||
sscanf(entry.fields[6], "%d/%d/%d", &(data->birthday.day), &(data->birthday.month), &(data->birthday.year));
|
||||
}
|
||||
|
||||
// Add a new person
|
||||
void population_add(tPopulation* data, tPerson person) {
|
||||
// Check input data
|
||||
assert(data != NULL);
|
||||
|
||||
// If person does not exist add it
|
||||
if(population_find(data[0], person.document) < 0) {
|
||||
// Allocate memory for new element
|
||||
if (data->count == 0) {
|
||||
// Request new memory space
|
||||
data->elems = (tPerson*) malloc(sizeof(tPerson));
|
||||
} else {
|
||||
// Modify currently allocated memory
|
||||
data->elems = (tPerson*) realloc(data->elems, (data->count + 1) * sizeof(tPerson));
|
||||
}
|
||||
assert(data->elems != NULL);
|
||||
|
||||
// Copy the data to the new position
|
||||
person_cpy(&(data->elems[data->count]), person);
|
||||
|
||||
// Increase the number of elements
|
||||
data->count ++;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove a person
|
||||
void population_del(tPopulation* data, const char *document) {
|
||||
int i;
|
||||
int pos;
|
||||
|
||||
// Check input data
|
||||
assert(data != NULL);
|
||||
|
||||
// Find if it exists
|
||||
pos = population_find(data[0], document);
|
||||
|
||||
if (pos >= 0) {
|
||||
// Remove current position memory
|
||||
person_free(&(data->elems[pos]));
|
||||
// Shift elements
|
||||
for(i = pos; i < data->count-1; i++) {
|
||||
// Copy address of element on position i+1 to position i
|
||||
data->elems[i] = data->elems[i+1];
|
||||
}
|
||||
// Update the number of elements
|
||||
data->count--;
|
||||
// Resize the used memory
|
||||
if (data->count == 0) {
|
||||
// No element remaining
|
||||
free(data->elems);
|
||||
data->elems = NULL;
|
||||
} else {
|
||||
// Still some elements are remaining
|
||||
data->elems = (tPerson*)realloc(data->elems, data->count * sizeof(tPerson));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the position of a person with provided document. -1 if it does not exist
|
||||
int population_find(tPopulation data, const char* document) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < data.count; i++) {
|
||||
if(strcmp(data.elems[i].document, document) == 0 ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Print the person data
|
||||
void population_print(tPopulation data) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < data.count; i++) {
|
||||
// Print position and document
|
||||
printf("%d;%s;", i, data.elems[i].document);
|
||||
// Print name and surname
|
||||
printf("%s;%s;", data.elems[i].name, data.elems[i].surname);
|
||||
// Print email
|
||||
printf("%s;", data.elems[i].email);
|
||||
// Print address and CP
|
||||
printf("%s;%s;", data.elems[i].address, data.elems[i].cp);
|
||||
// Print birthday date
|
||||
printf("%02d/%02d/%04d\n", data.elems[i].birthday.day, data.elems[i].birthday.month, data.elems[i].birthday.year);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the data from the source to destination
|
||||
void person_cpy(tPerson* destination, tPerson source) {
|
||||
// Copy identity document data
|
||||
destination->document = (char*) malloc((strlen(source.document) + 1) * sizeof(char));
|
||||
assert(destination->document != NULL);
|
||||
strcpy(destination->document, source.document);
|
||||
|
||||
// Copy name data
|
||||
destination->name = (char*) malloc((strlen(source.name) + 1) * sizeof(char));
|
||||
assert(destination->name != NULL);
|
||||
strcpy(destination->name, source.name);
|
||||
|
||||
// Copy surname data
|
||||
destination->surname = (char*) malloc((strlen(source.surname) + 1) * sizeof(char));
|
||||
assert(destination->surname != NULL);
|
||||
strcpy(destination->surname, source.surname);
|
||||
|
||||
// Copy email data
|
||||
destination->email = (char*) malloc((strlen(source.email) + 1) * sizeof(char));
|
||||
assert(destination->email != NULL);
|
||||
strcpy(destination->email, source.email);
|
||||
|
||||
// Copy address data
|
||||
destination->address = (char*) malloc((strlen(source.address) + 1) * sizeof(char));
|
||||
assert(destination->address != NULL);
|
||||
strcpy(destination->address, source.address);
|
||||
|
||||
// Copy cp data
|
||||
destination->cp = (char*) malloc((strlen(source.cp) + 1) * sizeof(char));
|
||||
assert(destination->cp != NULL);
|
||||
strcpy(destination->cp, source.cp);
|
||||
|
||||
// Copy the birthday date
|
||||
destination->birthday = source.birthday;
|
||||
}
|
||||
104
src/main.c
Normal file
104
src/main.c
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "test.h"
|
||||
#include "api.h"
|
||||
|
||||
typedef struct _AppArguments {
|
||||
char* app_name;
|
||||
char* out_file;
|
||||
char* in_file;
|
||||
bool wait_on_exit;
|
||||
} tAppArguments;
|
||||
|
||||
// Wait user key
|
||||
void waitKey(tAppArguments parameters) {
|
||||
if (parameters.wait_on_exit) {
|
||||
printf("Press key to continue...");
|
||||
getchar();
|
||||
}
|
||||
}
|
||||
|
||||
// Display help text
|
||||
void help(const char* app_name) {
|
||||
printf("%s [--help] [--in <input_test_file>] [--out <output_file>] [--test-out <output_test_file>]\n", app_name);
|
||||
printf("\t[%s] %s\n", "--help", "Show this help information.");
|
||||
printf("\t[%s] %s\n", "--no-wait", "Do not wait user key press on exit.");
|
||||
printf("\t[%s] %s\n", "--in", "Provide file with input test data in CSV format.");
|
||||
printf("\t[%s] %s\n", "--out", "Write the result of tests in a file in JSON format.");
|
||||
}
|
||||
|
||||
bool parseArguments(tAppArguments* arguments, int argc, char **argv) {
|
||||
int i;
|
||||
|
||||
// Initialize the arguments
|
||||
arguments->app_name = NULL;
|
||||
arguments->out_file = NULL;
|
||||
arguments->in_file = NULL;
|
||||
arguments->wait_on_exit = true;
|
||||
|
||||
// Parse input arguments
|
||||
arguments->app_name = argv[0];
|
||||
for (i=1; i < argc; i += 2) {
|
||||
if (strcmp(argv[i], "--help") == 0) {
|
||||
help(argv[0]);
|
||||
}
|
||||
if (strcmp(argv[i], "--no-wait") == 0) {
|
||||
arguments->wait_on_exit = false;
|
||||
}
|
||||
if (strcmp(argv[i], "--in") == 0) {
|
||||
if (argc < i + 1) {
|
||||
help(argv[0]);
|
||||
return false;
|
||||
}
|
||||
arguments->in_file = argv[i+1];
|
||||
}
|
||||
if (strcmp(argv[i], "--out") == 0) {
|
||||
if (argc < i + 1) {
|
||||
help(argv[0]);
|
||||
return false;
|
||||
}
|
||||
arguments->out_file = argv[i+1];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
tAppArguments parameters;
|
||||
tTestSuite testSuite;
|
||||
|
||||
// Parse input arguments
|
||||
if (!parseArguments(¶meters, argc, argv)) {
|
||||
printf("ERROR: Invalid input arguments");
|
||||
// Wait user to press a key to ensure error is shown
|
||||
waitKey(parameters);
|
||||
// Exit with error
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Initialize the test suite
|
||||
testSuite_init(&testSuite);
|
||||
|
||||
// Run all tests
|
||||
testSuite_run(&testSuite, parameters.in_file);
|
||||
|
||||
// Print test results
|
||||
testSuite_print(&testSuite);
|
||||
|
||||
// Store test results
|
||||
if (parameters.out_file != NULL) {
|
||||
testSuite_export(&testSuite, parameters.out_file);
|
||||
printf("Restults stored in %s\n", parameters.out_file);
|
||||
}
|
||||
|
||||
// Remove test suite data
|
||||
testSuite_free(&testSuite);
|
||||
|
||||
// Wait user to press a key to ensure results are shown
|
||||
waitKey(parameters);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
11
test/include/test.h
Normal file
11
test/include/test.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef __TEST__H
|
||||
#define __TEST__H
|
||||
#include "test_suite.h"
|
||||
|
||||
// Run all available tests
|
||||
void testSuite_run(tTestSuite* test_suite, const char* input);
|
||||
|
||||
// Check if README.txt is available and have the correct information
|
||||
//void readReadme(tTestSuite* test_suite);
|
||||
|
||||
#endif // __TEST__H
|
||||
20
test/include/test_pr1.h
Normal file
20
test/include/test_pr1.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef __TEST_PR1_H__
|
||||
#define __TEST_PR1_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "test_suite.h"
|
||||
|
||||
// Run all tests for PR1
|
||||
bool run_pr1(tTestSuite* test_suite, const char* input);
|
||||
|
||||
// Run tests for PR1 exercice 1
|
||||
bool run_pr1_ex1(tTestSection* test_section, const char* input);
|
||||
|
||||
// Run tests for PR1 exercice 2
|
||||
bool run_pr1_ex2(tTestSection* test_section, const char* input);
|
||||
|
||||
// Run tests for PR1 exercice 3
|
||||
bool run_pr1_ex3(tTestSection* test_section, const char* input);
|
||||
|
||||
|
||||
#endif // __TEST_PR1_H__
|
||||
151
test/include/test_suite.h
Normal file
151
test/include/test_suite.h
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
#ifndef __TEST_SUITE__H
|
||||
#define __TEST_SUITE__H
|
||||
#include <stdbool.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// #define PRINT_TEST_PROGRESS
|
||||
|
||||
// Size of the buffer used to read files data
|
||||
#define BUFFER_SIZE 2048
|
||||
|
||||
// Status of a test
|
||||
typedef enum {
|
||||
TEST_RUNNING,
|
||||
TEST_NOT_IMPLEMENTED,
|
||||
TEST_PASSED,
|
||||
TEST_FAILED
|
||||
} tTestResult;
|
||||
|
||||
// A single test
|
||||
typedef struct {
|
||||
// Code of the test
|
||||
char* code;
|
||||
// Description of the test
|
||||
char* description;
|
||||
// Result of the test
|
||||
tTestResult result;
|
||||
} tTest;
|
||||
|
||||
// Grup of tests
|
||||
typedef struct {
|
||||
// Code of the test section
|
||||
char* code;
|
||||
// Title of the section
|
||||
char* title;
|
||||
// Number of tests
|
||||
int numTests;
|
||||
// Array of tests
|
||||
tTest* tests;
|
||||
} tTestSection;
|
||||
|
||||
// Test suit learner data
|
||||
typedef struct {
|
||||
// Email
|
||||
char* email;
|
||||
// Username
|
||||
char* username;
|
||||
// First name
|
||||
char* first_name;
|
||||
// Last name
|
||||
char* last_name;
|
||||
// Environment
|
||||
char* environment;
|
||||
// Whether the learner data file exists or not
|
||||
bool file_exists;
|
||||
} tLearnerData;
|
||||
|
||||
// Test suit with multiple sections
|
||||
typedef struct {
|
||||
// Learner data
|
||||
tLearnerData learner;
|
||||
// Number of sections
|
||||
int numSections;
|
||||
// Array of sections
|
||||
tTestSection* sections;
|
||||
} tTestSuite;
|
||||
|
||||
// Initialize a test Suite
|
||||
void testSuite_init(tTestSuite* object);
|
||||
|
||||
// Load learner data
|
||||
bool testSuite_load_learner(tTestSuite* object, const char* file);
|
||||
|
||||
// Remove a test Suite
|
||||
void testSuite_free(tTestSuite* object);
|
||||
|
||||
// Add a test Section
|
||||
void testSuite_addSection(tTestSuite* object, const char* code, const char* title);
|
||||
|
||||
// Add a test
|
||||
void testSuite_addTest(tTestSuite* object, const char* section_code, const char* code, const char* description, tTestResult result);
|
||||
|
||||
// Update a test result
|
||||
void testSuite_updateTest(tTestSuite* object, const char* section_code, const char* test_code, tTestResult result);
|
||||
|
||||
// Get a pointer to a section
|
||||
tTestSection* testSuite_getSection(tTestSuite* object, const char* section_code);
|
||||
|
||||
// Get a pointer to a test
|
||||
tTest* testSuite_getTest(tTestSuite* object, const char* section_code, const char* test_code);
|
||||
|
||||
// Get test statistics
|
||||
void testSuite_getStats(tTestSuite* object, int* total, int* passed, int* failed, int* not_implemented);
|
||||
|
||||
// Print test suite
|
||||
void testSuite_print(tTestSuite* object);
|
||||
|
||||
// Export a test suite
|
||||
void testSuite_export(tTestSuite* object, const char* output);
|
||||
|
||||
|
||||
|
||||
// Initialize a test Section
|
||||
void testSection_init(tTestSection* object, const char* code, const char* title);
|
||||
|
||||
// Remove a test Section
|
||||
void testSection_free(tTestSection* object);
|
||||
|
||||
// Add a test to the Section
|
||||
void testSection_addTest(tTestSection* object, const char* code, const char* description, tTestResult result);
|
||||
|
||||
// Update a test result
|
||||
void testSection_updateTest(tTestSection* object, const char* test_code, tTestResult result);
|
||||
|
||||
// Get a pointer to a test
|
||||
tTest* testSection_getTest(tTestSection* object, const char* test_code);
|
||||
|
||||
// Get test statistics
|
||||
void testSection_getStats(tTestSection* object, int* total, int* passed, int* failed, int* not_implemented);
|
||||
|
||||
// Print test section
|
||||
void testSection_print(tTestSection* object);
|
||||
|
||||
// Export a test section
|
||||
void testSection_export(tTestSection* object, FILE* fout);
|
||||
|
||||
|
||||
|
||||
// Initialize a test
|
||||
void test_init(tTest* object, const char* code, const char* description, tTestResult result);
|
||||
|
||||
// Remove a test
|
||||
void test_free(tTest* object);
|
||||
|
||||
// Update a test result
|
||||
void test_updateTest(tTest* object, tTestResult result);
|
||||
|
||||
// Print test
|
||||
void test_print(tTest* object);
|
||||
|
||||
// Export a test
|
||||
void test_export(tTest* object, FILE* fout);
|
||||
|
||||
|
||||
// Start a test
|
||||
void start_test(tTestSection* section, const char* code, const char* description);
|
||||
|
||||
// Finish a test
|
||||
void end_test(tTestSection* section, const char* code, bool passed);
|
||||
|
||||
#endif // __TEST_SUITE__H
|
||||
39
test/src/test.c
Normal file
39
test/src/test.c
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "test.h"
|
||||
#include "test_pr1.h"
|
||||
|
||||
// Define default test data
|
||||
const char* test_data_str = "PERSON;87654321K;John;Smith;john.smith@example.com;My street, 25;08001;30/12/1980\n" \
|
||||
"PERSON;98765432J;Jane;Doe;jane.doe@example.com;Her street, 5;08500;12/01/1995\n" \
|
||||
"GEOLOCATION;87654321K;15/10/2021;13:41;41.3870;2.1698\n" \
|
||||
"GEOLOCATION;87654321K;15/10/2021;13:45;41.3870;2.1695\n" \
|
||||
"GEOLOCATION;98765432J;15/10/2021;13:50;41.3871;2.1697\n" \
|
||||
"GEOLOCATION;87654321K;15/10/2021;13:50;41.3871;2.1697\n";
|
||||
|
||||
// Run all available tests
|
||||
void testSuite_run(tTestSuite* test_suite, const char* input) {
|
||||
const char* default_input = "default_data.csv";
|
||||
FILE *fout;
|
||||
const char* filename;
|
||||
|
||||
assert(test_suite != NULL);
|
||||
|
||||
// Load the README.txt file
|
||||
testSuite_load_learner(test_suite, "../README.txt");
|
||||
|
||||
// If no file is provided, use default data
|
||||
if (input == NULL) {
|
||||
filename = default_input;
|
||||
fout = fopen(filename, "w");
|
||||
assert(fout != NULL);
|
||||
fwrite(test_data_str, strlen(test_data_str), 1, fout);
|
||||
fclose(fout);
|
||||
} else {
|
||||
filename = input;
|
||||
}
|
||||
|
||||
// Run tests for PR1
|
||||
run_pr1(test_suite, filename);
|
||||
}
|
||||
|
||||
364
test/src/test_pr1.c
Normal file
364
test/src/test_pr1.c
Normal file
|
|
@ -0,0 +1,364 @@
|
|||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "test_pr1.h"
|
||||
#include "api.h"
|
||||
|
||||
// Run all tests for PR1
|
||||
bool run_pr1(tTestSuite* test_suite, const char* input) {
|
||||
bool ok = true;
|
||||
tTestSection* section = NULL;
|
||||
|
||||
assert(test_suite != NULL);
|
||||
|
||||
testSuite_addSection(test_suite, "PR1", "Tests for PR1 exercices");
|
||||
|
||||
section = testSuite_getSection(test_suite, "PR1");
|
||||
assert(section != NULL);
|
||||
|
||||
ok = run_pr1_ex1(section, input);
|
||||
ok = run_pr1_ex2(section, input) && ok;
|
||||
ok = run_pr1_ex3(section, input) && ok;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Run all tests for Exercice 1 of PR1
|
||||
bool run_pr1_ex1(tTestSection* test_section, const char* input) {
|
||||
bool passed = true, failed = false;
|
||||
const char* version;
|
||||
|
||||
/////////////////////////////
|
||||
///// PR1 EX1 TEST 1 //////
|
||||
/////////////////////////////
|
||||
failed = false;
|
||||
start_test(test_section, "PR1_EX1_1", "Read version information.");
|
||||
// Get the version+
|
||||
version = api_version();
|
||||
if (strcmp(version, "UOC PP 20211") != 0) {
|
||||
failed = true;
|
||||
passed = false;
|
||||
}
|
||||
end_test(test_section, "PR1_EX1_1", !failed);
|
||||
|
||||
return passed;
|
||||
}
|
||||
|
||||
// Run all tests for Exercice 2 of PR1
|
||||
bool run_pr1_ex2(tTestSection* test_section, const char* input) {
|
||||
tApiData data;
|
||||
tApiError error;
|
||||
tCSVEntry entry;
|
||||
tCSVEntry entry2;
|
||||
bool passed = true, failed = false;
|
||||
bool fail_all = false;
|
||||
|
||||
/////////////////////////////
|
||||
///// PR1 EX2 TEST 1 //////
|
||||
/////////////////////////////
|
||||
failed = false;
|
||||
start_test(test_section, "PR1_EX2_1", "Initialize the API data structure");
|
||||
// Initialize the data
|
||||
error = api_initData(&data);
|
||||
if (error != E_SUCCESS) {
|
||||
failed = true;
|
||||
passed = false;
|
||||
fail_all = true;
|
||||
}
|
||||
end_test(test_section, "PR1_EX2_1", !failed);
|
||||
|
||||
/////////////////////////////
|
||||
///// PR1 EX2 TEST 2 //////
|
||||
/////////////////////////////
|
||||
failed = false;
|
||||
start_test(test_section, "PR1_EX2_2", "Load data from file");
|
||||
// Load basic data to the API
|
||||
if (fail_all) {
|
||||
failed = true;
|
||||
} else {
|
||||
error = api_loadData(&data, input, true);
|
||||
if (error != E_SUCCESS) {
|
||||
failed = true;
|
||||
passed = false;
|
||||
}
|
||||
}
|
||||
end_test(test_section, "PR1_EX2_2", !failed);
|
||||
|
||||
/////////////////////////////
|
||||
///// PR1 EX2 TEST 3 //////
|
||||
/////////////////////////////
|
||||
failed = false;
|
||||
start_test(test_section, "PR1_EX2_3", "Add an entry with invalid type");
|
||||
// Create an entry with invalid type
|
||||
csv_initEntry(&entry);
|
||||
csv_parseEntry(&entry, "68765432L;Jane;Doe;jane.doe2@example.com;Her street, 15;08500;12/01/1995", "INVALID_TYPE");
|
||||
if (fail_all) {
|
||||
failed = true;
|
||||
} else {
|
||||
// Add the entry
|
||||
error = api_addDataEntry(&data, entry);
|
||||
if (error != E_INVALID_ENTRY_TYPE) {
|
||||
failed = true;
|
||||
passed = false;
|
||||
}
|
||||
}
|
||||
end_test(test_section, "PR1_EX2_3", !failed);
|
||||
// Free memory
|
||||
csv_freeEntry(&entry);
|
||||
|
||||
/////////////////////////////
|
||||
///// PR1 EX2 TEST 4 //////
|
||||
/////////////////////////////
|
||||
failed = false;
|
||||
start_test(test_section, "PR1_EX2_4", "Add a person entry with invalid format");
|
||||
// Create an entry with invalid number of fields
|
||||
csv_initEntry(&entry);
|
||||
csv_parseEntry(&entry, "PERSON;68765432L;Jane;Doe;jane.doe2@example.com;Her street, 15;08500", NULL);
|
||||
if (fail_all) {
|
||||
failed = true;
|
||||
} else {
|
||||
error = api_addDataEntry(&data, entry);
|
||||
if (error != E_INVALID_ENTRY_FORMAT) {
|
||||
failed = true;
|
||||
passed = false;
|
||||
}
|
||||
}
|
||||
end_test(test_section, "PR1_EX2_4", !failed);
|
||||
|
||||
// Free memory
|
||||
csv_freeEntry(&entry);
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
///// PR1 EX2 TEST 5 //////
|
||||
/////////////////////////////
|
||||
failed = false;
|
||||
start_test(test_section, "PR1_EX2_5", "Add a geoposition entry with invalid format");
|
||||
// Create an entry with invalid number of fields
|
||||
csv_initEntry(&entry);
|
||||
csv_parseEntry(&entry, "GEOLOCATION;87654321K;15/10/2021;13:41;41.3870;2.1698;Extra comment", NULL);
|
||||
if (fail_all) {
|
||||
failed = true;
|
||||
} else {
|
||||
error = api_addDataEntry(&data, entry);
|
||||
if (error != E_INVALID_ENTRY_FORMAT) {
|
||||
failed = true;
|
||||
passed = false;
|
||||
}
|
||||
}
|
||||
end_test(test_section, "PR1_EX2_5", !failed);
|
||||
// Free memory
|
||||
csv_freeEntry(&entry);
|
||||
|
||||
/////////////////////////////
|
||||
///// PR1 EX2 TEST 6 //////
|
||||
/////////////////////////////
|
||||
failed = false;
|
||||
start_test(test_section, "PR1_EX2_6", "Add a duplicated person");
|
||||
// Create an entry
|
||||
csv_initEntry(&entry);
|
||||
csv_parseEntry(&entry, "PERSON;68765432L;Jane;Doe;jane.doe2@example.com;Her street, 15;08500;12/01/1995", NULL);
|
||||
|
||||
if (fail_all) {
|
||||
failed = true;
|
||||
} else {
|
||||
// Insert once to ensure it is present
|
||||
api_addDataEntry(&data, entry);
|
||||
// Try to insert it again
|
||||
error = api_addDataEntry(&data, entry);
|
||||
if (error != E_DUPLICATED_ENTRY) {
|
||||
failed = true;
|
||||
passed = false;
|
||||
}
|
||||
}
|
||||
end_test(test_section, "PR1_EX2_6", !failed);
|
||||
// Free memory
|
||||
csv_freeEntry(&entry);
|
||||
|
||||
/////////////////////////////
|
||||
///// PR1 EX2 TEST 7 //////
|
||||
/////////////////////////////
|
||||
failed = false;
|
||||
start_test(test_section, "PR1_EX2_7", "Add a duplicated geoposition");
|
||||
// Create an entry
|
||||
csv_initEntry(&entry);
|
||||
csv_parseEntry(&entry, "GEOLOCATION;87654321K;15/10/2021;13:41;41.3870;2.1698", NULL);
|
||||
if (fail_all) {
|
||||
failed = true;
|
||||
} else {
|
||||
// Insert once to ensure it is present
|
||||
api_addDataEntry(&data, entry);
|
||||
// Try to insert it again
|
||||
error = api_addDataEntry(&data, entry);
|
||||
if (error != E_DUPLICATED_ENTRY) {
|
||||
failed = true;
|
||||
passed = false;
|
||||
}
|
||||
}
|
||||
end_test(test_section, "PR1_EX2_7", !failed);
|
||||
// Free memory
|
||||
csv_freeEntry(&entry);
|
||||
|
||||
/////////////////////////////
|
||||
///// PR1 EX2 TEST 8 //////
|
||||
/////////////////////////////
|
||||
failed = false;
|
||||
start_test(test_section, "PR1_EX2_8", "Remove all data");
|
||||
|
||||
// Create a person entry
|
||||
csv_initEntry(&entry);
|
||||
csv_parseEntry(&entry, "PERSON;87654321K;Jane;Doe;jane.doe2@example.com;Her street, 15;08500;12/01/1995", NULL);
|
||||
|
||||
// Create a geodata entry
|
||||
csv_initEntry(&entry2);
|
||||
csv_parseEntry(&entry2, "GEOLOCATION;87654321K;15/10/2021;13:41;41.3870;2.1698", NULL);
|
||||
if (fail_all) {
|
||||
failed = true;
|
||||
} else {
|
||||
// Ensure we cannot insert them
|
||||
if (api_addDataEntry(&data, entry) != E_DUPLICATED_ENTRY || api_addDataEntry(&data, entry2) != E_DUPLICATED_ENTRY) {
|
||||
failed = true;
|
||||
passed = false;
|
||||
} else {
|
||||
// Remove all data
|
||||
api_freeData(&data);
|
||||
|
||||
// Try to insert again
|
||||
if (api_addDataEntry(&data, entry) != E_SUCCESS || api_addDataEntry(&data, entry2) != E_SUCCESS) {
|
||||
failed = true;
|
||||
passed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
end_test(test_section, "PR1_EX2_8", !failed);
|
||||
// Free memory
|
||||
csv_freeEntry(&entry);
|
||||
csv_freeEntry(&entry2);
|
||||
|
||||
return passed;
|
||||
}
|
||||
|
||||
// Run all tests for Exercice 3 of PR1
|
||||
bool run_pr1_ex3(tTestSection* test_section, const char* input) {
|
||||
tApiData data;
|
||||
tApiError error;
|
||||
tCSVEntry entry;
|
||||
tCSVEntry person;
|
||||
tCSVData geoData;
|
||||
bool passed = true, failed = false;
|
||||
bool fail_all = false;
|
||||
|
||||
// Load basic data to the API
|
||||
if (api_initData(&data) != E_SUCCESS) {
|
||||
fail_all = true;
|
||||
}
|
||||
if (!fail_all && api_loadData(&data, input, true) != E_SUCCESS) {
|
||||
fail_all = true;
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
///// PR1 EX3 TEST 1 //////
|
||||
/////////////////////////////
|
||||
failed = false;
|
||||
start_test(test_section, "PR1_EX3_1", "Find an exixting person");
|
||||
if (fail_all) {
|
||||
failed = true;
|
||||
} else {
|
||||
// Create a person entry to ensure it exists
|
||||
csv_initEntry(&entry);
|
||||
csv_parseEntry(&entry, "PERSON;87654321K;Jane;Doe;jane.doe2@example.com;Her street, 15;08500;12/01/1995", NULL);
|
||||
api_addDataEntry(&data, entry);
|
||||
error = api_findPerson(&data, "87654321K", &person);
|
||||
if (error != E_SUCCESS || csv_numFields(person) != 7) {
|
||||
failed = true;
|
||||
}
|
||||
// Free memory
|
||||
csv_freeEntry(&entry);
|
||||
csv_freeEntry(&person);
|
||||
|
||||
}
|
||||
end_test(test_section, "PR1_EX3_1", !failed);
|
||||
|
||||
/////////////////////////////
|
||||
///// PR1 EX3 TEST 2 //////
|
||||
/////////////////////////////
|
||||
failed = false;
|
||||
start_test(test_section, "PR1_EX3_2", "Find a non exixting person");
|
||||
if (fail_all) {
|
||||
failed = true;
|
||||
} else {
|
||||
error = api_findPerson(&data, "00000000L", &person);
|
||||
if (error != E_PERSON_NOT_FOUND) {
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
end_test(test_section, "PR1_EX3_2", !failed);
|
||||
|
||||
/////////////////////////////
|
||||
///// PR1 EX3 TEST 3 //////
|
||||
/////////////////////////////
|
||||
failed = false;
|
||||
start_test(test_section, "PR1_EX3_3", "Get geoplocation from an exixting person");
|
||||
if (fail_all) {
|
||||
failed = true;
|
||||
} else {
|
||||
error = api_getPersonGeolocation(&data, "87654321K", &geoData);
|
||||
if (error != E_SUCCESS) {
|
||||
failed = true;
|
||||
}
|
||||
// Free memory
|
||||
csv_free(&geoData);
|
||||
}
|
||||
end_test(test_section, "PR1_EX3_3", !failed);
|
||||
|
||||
/////////////////////////////
|
||||
///// PR1 EX3 TEST 4 //////
|
||||
/////////////////////////////
|
||||
failed = false;
|
||||
start_test(test_section, "PR1_EX3_4", "Get geoplocation from a non exixting person");
|
||||
if (fail_all) {
|
||||
failed = true;
|
||||
} else {
|
||||
error = api_getPersonGeolocation(&data, "00000000L", &geoData);
|
||||
if (error != E_PERSON_NOT_FOUND) {
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
end_test(test_section, "PR1_EX3_4", !failed);
|
||||
|
||||
/////////////////////////////
|
||||
///// PR1 EX3 TEST 5 //////
|
||||
/////////////////////////////
|
||||
failed = false;
|
||||
start_test(test_section, "PR1_EX3_5", "Remove an exixting person");
|
||||
if (fail_all) {
|
||||
failed = true;
|
||||
} else {
|
||||
error = api_removePerson(&data, "87654321K");
|
||||
if (error != E_SUCCESS) {
|
||||
failed = true;
|
||||
} else {
|
||||
error = api_getPersonGeolocation(&data, "87654321K", &geoData);
|
||||
if (error != E_PERSON_NOT_FOUND) {
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
end_test(test_section, "PR1_EX3_5", !failed);
|
||||
|
||||
/////////////////////////////
|
||||
///// PR1 EX3 TEST 6 //////
|
||||
/////////////////////////////
|
||||
failed = false;
|
||||
start_test(test_section, "PR1_EX3_6", "Remove a non exixting person");
|
||||
if (fail_all) {
|
||||
failed = true;
|
||||
} else {
|
||||
if (error != E_PERSON_NOT_FOUND) {
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
end_test(test_section, "PR1_EX3_6", !failed);
|
||||
|
||||
return passed;
|
||||
}
|
||||
559
test/src/test_suite.c
Normal file
559
test/src/test_suite.c
Normal file
|
|
@ -0,0 +1,559 @@
|
|||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "test_suite.h"
|
||||
|
||||
// Initialize a test Suite
|
||||
void testSuite_init(tTestSuite* object) {
|
||||
assert(object != NULL);
|
||||
object->learner.email = NULL;
|
||||
object->learner.username = NULL;
|
||||
object->learner.first_name = NULL;
|
||||
object->learner.last_name = NULL;
|
||||
object->learner.environment = NULL;
|
||||
object->learner.file_exists = false;
|
||||
object->numSections = 0;
|
||||
object->sections = NULL;
|
||||
}
|
||||
|
||||
// Load learner data
|
||||
bool testSuite_load_learner(tTestSuite* object, const char* file) {
|
||||
char buffer[BUFFER_SIZE];
|
||||
FILE *fin=NULL;
|
||||
int state;
|
||||
char* pos;
|
||||
|
||||
assert(object != NULL);
|
||||
assert(file != NULL);
|
||||
|
||||
fin = fopen(file, "r");
|
||||
if (fin == NULL) {
|
||||
object->learner.email = NULL;
|
||||
object->learner.username = NULL;
|
||||
object->learner.first_name = NULL;
|
||||
object->learner.last_name = NULL;
|
||||
object->learner.environment = NULL;
|
||||
object->learner.file_exists = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
state = 0;
|
||||
while (fgets(buffer, BUFFER_SIZE, fin)) {
|
||||
if (state == 0) {
|
||||
// Read email
|
||||
object->learner.email = (char*) malloc((strlen(buffer) + 1) * sizeof(char));
|
||||
memset(object->learner.email, 0, (strlen(buffer) + 1) * sizeof(char));
|
||||
strncpy(object->learner.email, buffer, strcspn(buffer, "\n\r"));
|
||||
} else if(state == 1) {
|
||||
// Read Surname, Name
|
||||
pos = strchr(buffer, ',');
|
||||
if (pos > 0) {
|
||||
// Copy the surnames
|
||||
object->learner.last_name = (char*) malloc((pos - buffer) * sizeof(char));
|
||||
memset(object->learner.last_name, 0, (pos - buffer) * sizeof(char));
|
||||
strncpy(object->learner.last_name, buffer, strcspn(buffer, ",") - 1);
|
||||
// Skip the comma
|
||||
pos++;
|
||||
// Skip initial blank spaces
|
||||
while (pos < &buffer[BUFFER_SIZE] && *pos==' ') pos++;
|
||||
// Copy the first name
|
||||
object->learner.first_name = (char*) malloc((strlen(pos) + 1) * sizeof(char));
|
||||
memset(object->learner.first_name, 0, (strlen(pos) + 1) * sizeof(char));
|
||||
strncpy(object->learner.first_name, pos, strcspn(pos, "\n\r"));
|
||||
} else {
|
||||
object->learner.first_name = (char*) malloc((strlen(buffer) + 1) * sizeof(char));
|
||||
memset(object->learner.first_name, 0, (strlen(buffer) + 1) * sizeof(char));
|
||||
strcpy(object->learner.first_name, buffer);
|
||||
}
|
||||
} else if(state == 2) {
|
||||
object->learner.environment = (char*) malloc((strlen(buffer) + 1) * sizeof(char));
|
||||
strcpy(object->learner.environment, buffer);
|
||||
} else if(state > 2) {
|
||||
object->learner.environment = (char*) realloc(object->learner.environment, (strlen(object->learner.environment) + strlen(buffer) + 1) * sizeof(char));
|
||||
strcat(object->learner.environment, buffer);
|
||||
}
|
||||
state ++;
|
||||
}
|
||||
|
||||
object->learner.file_exists = true;
|
||||
|
||||
fclose(fin);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove a test Suite
|
||||
void testSuite_free(tTestSuite* object) {
|
||||
int i;
|
||||
assert(object != NULL);
|
||||
// Free learner data
|
||||
if(object->learner.email != NULL) {
|
||||
free(object->learner.email);
|
||||
object->learner.email = NULL;
|
||||
}
|
||||
if(object->learner.username != NULL) {
|
||||
free(object->learner.username);
|
||||
object->learner.username = NULL;
|
||||
}
|
||||
if(object->learner.first_name != NULL) {
|
||||
free(object->learner.first_name);
|
||||
object->learner.first_name = NULL;
|
||||
}
|
||||
if(object->learner.last_name != NULL) {
|
||||
free(object->learner.last_name);
|
||||
object->learner.last_name = NULL;
|
||||
}
|
||||
if(object->learner.environment != NULL) {
|
||||
free(object->learner.environment);
|
||||
object->learner.environment = NULL;
|
||||
}
|
||||
object->learner.file_exists = false;
|
||||
// Free test data
|
||||
if(object->sections != NULL) {
|
||||
for(i = 0; i < object->numSections; i++) {
|
||||
testSection_free(&(object->sections[i]));
|
||||
}
|
||||
free(object->sections);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a test Section
|
||||
void testSuite_addSection(tTestSuite* object, const char* code, const char* title) {
|
||||
assert(object != NULL);
|
||||
object->numSections++;
|
||||
if(object->sections == NULL) {
|
||||
object->sections = (tTestSection*)malloc(object->numSections * sizeof(tTestSection));
|
||||
} else {
|
||||
object->sections = (tTestSection*)realloc(object->sections, object->numSections * sizeof(tTestSection));
|
||||
}
|
||||
assert(object->sections != NULL);
|
||||
testSection_init(&(object->sections[object->numSections - 1]), code, title);
|
||||
}
|
||||
|
||||
// Add a test
|
||||
void testSuite_addTest(tTestSuite* object, const char* section_code, const char* code, const char* description, tTestResult result) {
|
||||
tTestSection* section = NULL;
|
||||
assert(object != NULL);
|
||||
assert(section_code != NULL);
|
||||
assert(code != NULL);
|
||||
assert(description != NULL);
|
||||
|
||||
section = testSuite_getSection(object, section_code);
|
||||
assert(section != NULL);
|
||||
|
||||
testSection_addTest(section, code, description, result);
|
||||
}
|
||||
|
||||
// Update a test result
|
||||
void testSuite_updateTest(tTestSuite* object, const char* section_code, const char* test_code, tTestResult result) {
|
||||
tTestSection* section = NULL;
|
||||
|
||||
assert(object != NULL);
|
||||
assert(section_code != NULL);
|
||||
assert(test_code != NULL);
|
||||
|
||||
section = testSuite_getSection(object, section_code);
|
||||
assert(section != NULL);
|
||||
|
||||
testSection_updateTest(section, test_code, result);
|
||||
}
|
||||
|
||||
// Get a pointer to a section
|
||||
tTestSection* testSuite_getSection(tTestSuite* object, const char* section_code) {
|
||||
int i;
|
||||
|
||||
assert(object != NULL);
|
||||
assert(section_code != NULL);
|
||||
for(i = 0; i < object->numSections; i++) {
|
||||
if(strcmp(object->sections[i].code, section_code) == 0) {
|
||||
return &(object->sections[i]);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Get a pointer to a test
|
||||
tTest* testSuite_getTest(tTestSuite* object, const char* section_code, const char* test_code) {
|
||||
tTestSection* section = NULL;
|
||||
|
||||
assert(object != NULL);
|
||||
assert(section_code != NULL);
|
||||
assert(test_code != NULL);
|
||||
section = testSuite_getSection(object, section_code);
|
||||
assert(section != NULL);
|
||||
|
||||
if(section != NULL) {
|
||||
return testSection_getTest(section, test_code);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Get test statistics
|
||||
void testSuite_getStats(tTestSuite* object, int* total, int* passed, int* failed, int* not_implemented) {
|
||||
int i;
|
||||
int s_total, s_passed, s_failed, s_not_implemented;
|
||||
assert(object != NULL);
|
||||
assert(total != NULL);
|
||||
assert(passed != NULL);
|
||||
assert(failed != NULL);
|
||||
assert(not_implemented != NULL);
|
||||
|
||||
*total = 0;
|
||||
*passed = 0;
|
||||
*failed = 0;
|
||||
*not_implemented = 0;
|
||||
for(i = 0; i < object->numSections; i++) {
|
||||
testSection_getStats(&(object->sections[i]), &s_total, &s_passed, &s_failed, &s_not_implemented);
|
||||
*total += s_total;
|
||||
*passed += s_passed;
|
||||
*failed += s_failed;
|
||||
*not_implemented += s_not_implemented;
|
||||
}
|
||||
}
|
||||
|
||||
// Print test suite
|
||||
void testSuite_print(tTestSuite* object) {
|
||||
int i;
|
||||
int total, passed, failed, not_implemented;
|
||||
|
||||
assert(object != NULL);
|
||||
|
||||
// Print the header
|
||||
if (object->learner.file_exists) {
|
||||
printf("\n=========================================================================\n");
|
||||
if (object->learner.first_name != NULL && object->learner.last_name != NULL) {
|
||||
printf("\t Name: %s %s\n", object->learner.first_name, object->learner.last_name);
|
||||
} else {
|
||||
printf("\t Name: <not provided>\n");
|
||||
}
|
||||
if (object->learner.email != NULL) {
|
||||
printf("\t Email: %s\n", object->learner.email);
|
||||
} else {
|
||||
printf("\t Email: <not provided>\n");
|
||||
}
|
||||
printf("=========================================================================\n");
|
||||
} else {
|
||||
printf("\n=========================================================================\n");
|
||||
printf("\t NO LEARNER DATA\n");
|
||||
printf("=========================================================================\n");
|
||||
}
|
||||
|
||||
testSuite_getStats(object, &total, &passed, &failed, ¬_implemented);
|
||||
|
||||
printf("\n=========================================================================\n");
|
||||
printf("\t TEST RESULTS\n");
|
||||
printf("=========================================================================\n");
|
||||
if(object->numSections == 0) {
|
||||
printf("NO TEST DEFINED\n");
|
||||
} else {
|
||||
for(i = 0; i < object->numSections; i++) {
|
||||
testSection_print(&(object->sections[i]));
|
||||
}
|
||||
}
|
||||
printf("\n=========================================================================\n");
|
||||
if(total > 0) {
|
||||
printf("Total Tests: %d\n", total);
|
||||
printf("Passed Tests: %d ( %2.02f %% )\n", passed, ((float)passed / (float)total) * 100.0);
|
||||
printf("Failed Tests: %d ( %2.02f %% )\n", failed, ((float)failed / (float)total) * 100.0);
|
||||
//printf("Not Implemented: %d ( %2.02f %% )\n", not_implemented, ((float)not_implemented/(float)total)*100.0);
|
||||
printf("=========================================================================\n");
|
||||
}
|
||||
}
|
||||
|
||||
void write_nullable_field(FILE* fout, const char* value) {
|
||||
if (value == NULL) {
|
||||
fprintf(fout, "null");
|
||||
} else {
|
||||
fprintf(fout, "\"%s\"", value);
|
||||
}
|
||||
}
|
||||
|
||||
// Export a test suite
|
||||
void testSuite_export(tTestSuite* object, const char* output) {
|
||||
int i;
|
||||
int total, passed, failed, not_implemented;
|
||||
FILE* fout = NULL;
|
||||
|
||||
assert(object != NULL);
|
||||
assert(output != NULL);
|
||||
|
||||
fout = fopen(output, "w");
|
||||
assert(fout != NULL);
|
||||
|
||||
fprintf(fout, "{ \"learner\": {\"first_name\": ");
|
||||
write_nullable_field(fout, object->learner.first_name);
|
||||
fprintf(fout, ", \"last_name\": ");
|
||||
write_nullable_field(fout, object->learner.last_name);
|
||||
fprintf(fout, ", \"email\": ");
|
||||
write_nullable_field(fout, object->learner.email);
|
||||
fprintf(fout, ", \"username\": ");
|
||||
write_nullable_field(fout, object->learner.username);
|
||||
fprintf(fout, ", \"environment\": ");
|
||||
write_nullable_field(fout, object->learner.environment);
|
||||
fprintf(fout, "}, ");
|
||||
|
||||
testSuite_getStats(object, &total, &passed, &failed, ¬_implemented);
|
||||
|
||||
fprintf(fout, "{ \"total\": %d, \"passed\": %d, \"failed\": %d, \"not_implemented\": %d, \"sections\": [", total, passed, failed, not_implemented);
|
||||
|
||||
for(i = 0; i < object->numSections; i++) {
|
||||
if(i > 0) {
|
||||
fprintf(fout, ", ");
|
||||
}
|
||||
testSection_export(&(object->sections[i]), fout);
|
||||
}
|
||||
|
||||
fprintf(fout, "]}");
|
||||
fclose(fout);
|
||||
}
|
||||
|
||||
|
||||
// Initialize a test Section
|
||||
void testSection_init(tTestSection* object, const char* code, const char* title) {
|
||||
assert(object != NULL);
|
||||
object->code = (char*) malloc((strlen(code) + 1) * sizeof(char));
|
||||
assert(object->code != NULL);
|
||||
strcpy(object->code, code);
|
||||
object->title = (char*) malloc((strlen(title) + 1) * sizeof(char));
|
||||
assert(object->title != NULL);
|
||||
strcpy(object->title, title);
|
||||
object->numTests = 0;
|
||||
object->tests = NULL;
|
||||
}
|
||||
|
||||
// Remove a test Section
|
||||
void testSection_free(tTestSection* object) {
|
||||
int i;
|
||||
assert(object != NULL);
|
||||
assert(object->code != NULL);
|
||||
|
||||
free(object->code);
|
||||
free(object->title);
|
||||
if(object->tests != NULL) {
|
||||
for(i = 0; i < object->numTests; i++) {
|
||||
test_free(&(object->tests[i]));
|
||||
}
|
||||
free(object->tests);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Add a test to the Section
|
||||
void testSection_addTest(tTestSection* object, const char* code, const char* description, tTestResult result) {
|
||||
assert(object != NULL);
|
||||
object->numTests++;
|
||||
if(object->tests == NULL) {
|
||||
object->tests = (tTest*)malloc(object->numTests * sizeof(tTest));
|
||||
} else {
|
||||
object->tests = (tTest*)realloc(object->tests, object->numTests * sizeof(tTestSection));
|
||||
}
|
||||
assert(object->tests != NULL);
|
||||
test_init(&(object->tests[object->numTests - 1]), code, description, result);
|
||||
}
|
||||
|
||||
// Update a test result
|
||||
void testSection_updateTest(tTestSection* object, const char* test_code, tTestResult result) {
|
||||
tTest* test = NULL;
|
||||
|
||||
assert(object != NULL);
|
||||
test = testSection_getTest(object, test_code);
|
||||
|
||||
assert(test != NULL);
|
||||
test_updateTest(test, result);
|
||||
}
|
||||
|
||||
// Get a pointer to a test
|
||||
tTest* testSection_getTest(tTestSection* object, const char* test_code) {
|
||||
int i;
|
||||
assert(object != NULL);
|
||||
assert(test_code != NULL);
|
||||
for(i = 0; i < object->numTests; i++) {
|
||||
if(strcmp(object->tests[i].code, test_code) == 0) {
|
||||
return &(object->tests[i]);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Get test statistics
|
||||
void testSection_getStats(tTestSection* object, int* total, int* passed, int* failed, int* not_implemented) {
|
||||
int i;
|
||||
assert(object != NULL);
|
||||
assert(total != NULL);
|
||||
assert(passed != NULL);
|
||||
assert(failed != NULL);
|
||||
assert(not_implemented != NULL);
|
||||
|
||||
*total = object->numTests;
|
||||
*passed = 0;
|
||||
*failed = 0;
|
||||
*not_implemented = 0;
|
||||
for(i = 0; i < object->numTests; i++) {
|
||||
if(object->tests[i].result == TEST_PASSED) {
|
||||
(*passed)++;
|
||||
} else
|
||||
if(object->tests[i].result == TEST_FAILED) {
|
||||
(*failed)++;
|
||||
} else
|
||||
if(object->tests[i].result == TEST_FAILED) {
|
||||
(*not_implemented)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Print test section
|
||||
void testSection_print(tTestSection* object) {
|
||||
int i;
|
||||
int total, passed, failed, not_implemented;
|
||||
|
||||
assert(object != NULL);
|
||||
|
||||
testSection_getStats(object, &total, &passed, &failed, ¬_implemented);
|
||||
|
||||
printf("\n\t=================================================================\n");
|
||||
printf("\t%s\n", object->title);
|
||||
printf("\t=================================================================\n");
|
||||
if(object->numTests == 0) {
|
||||
printf("\tNO TEST DEFINED\n");
|
||||
} else {
|
||||
for(i = 0; i < object->numTests; i++) {
|
||||
test_print(&(object->tests[i]));
|
||||
}
|
||||
}
|
||||
printf("\t=================================================================\n");
|
||||
if(total > 0) {
|
||||
printf("\tTotal Tests: %d\n", total);
|
||||
printf("\tPassed Tests: %d ( %2.2f %% )\n", passed, ((float)passed / (float)total) * 100.0);
|
||||
printf("\tFailed Tests: %d ( %2.2f %%)\n", failed, ((float)failed / (float)total) * 100.0);
|
||||
//printf("\tNot Implemented: %d ( %2.2f %%)\n", not_implemented, ((float)not_implemented/(float)total)*100.0);
|
||||
printf("\t=================================================================\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Export a test section
|
||||
void testSection_export(tTestSection* object, FILE* fout) {
|
||||
int i;
|
||||
int total, passed, failed, not_implemented;
|
||||
|
||||
assert(object != NULL);
|
||||
assert(fout != NULL);
|
||||
|
||||
testSection_getStats(object, &total, &passed, &failed, ¬_implemented);
|
||||
|
||||
fprintf(fout, "{ \"code\": \"%s\", \"title\": \"%s\", \"total\": %d, \"passed\": %d, \"failed\": %d, \"not_implemented\": %d, \"tests\": [", object->code, object->title, total, passed, failed, not_implemented);
|
||||
|
||||
for(i = 0; i < object->numTests; i++) {
|
||||
if(i > 0) {
|
||||
fprintf(fout, ", ");
|
||||
}
|
||||
test_export(&(object->tests[i]), fout);
|
||||
}
|
||||
|
||||
fprintf(fout, "]}");
|
||||
}
|
||||
|
||||
|
||||
// Initialize a test
|
||||
void test_init(tTest* object, const char* code, const char* description, tTestResult result) {
|
||||
assert(object != NULL);
|
||||
object->code = (char*) malloc((strlen(code) + 1) * sizeof(char));
|
||||
assert(object->code != NULL);
|
||||
object->description = (char*) malloc((strlen(description) + 1) * sizeof(char));
|
||||
assert(object->description != NULL);
|
||||
strcpy(object->code, code);
|
||||
strcpy(object->description, description);
|
||||
object->result = TEST_RUNNING;
|
||||
}
|
||||
|
||||
// Remove a test
|
||||
void test_free(tTest* object) {
|
||||
assert(object != NULL);
|
||||
assert(object->code != NULL);
|
||||
assert(object->description != NULL);
|
||||
free(object->code);
|
||||
free(object->description);
|
||||
}
|
||||
|
||||
// Update a test result
|
||||
void test_updateTest(tTest* object, tTestResult result) {
|
||||
assert(object != NULL);
|
||||
object->result = result;
|
||||
}
|
||||
|
||||
// Print test
|
||||
void test_print(tTest* object) {
|
||||
assert(object != NULL);
|
||||
printf("\t\t");
|
||||
if(object->result == TEST_RUNNING) {
|
||||
printf("[%s]", "RUNNING");
|
||||
} else
|
||||
if(object->result == TEST_NOT_IMPLEMENTED) {
|
||||
printf("[%s]", "NOT IMPLEMENTED");
|
||||
} else
|
||||
if(object->result == TEST_PASSED) {
|
||||
printf("[%s]", "OK");
|
||||
} else
|
||||
if(object->result == TEST_FAILED) {
|
||||
printf("[%s]", "FAIL");
|
||||
}
|
||||
printf(":\t [%s] %s\n", object->code, object->description);
|
||||
}
|
||||
|
||||
// Export a test
|
||||
void test_export(tTest* object, FILE* fout) {
|
||||
assert(object != NULL);
|
||||
assert(fout != NULL);
|
||||
|
||||
fprintf(fout, "{ \"code\": \"%s\", \"description\": \"%s\", \"result\": ", object->code, object->description);
|
||||
if(object->result == TEST_RUNNING) {
|
||||
fprintf(fout, "\"%s\"}", "RUNNING");
|
||||
} else
|
||||
if(object->result == TEST_NOT_IMPLEMENTED) {
|
||||
fprintf(fout, "\"%s\"}", "NOT IMPLEMENTED");
|
||||
} else
|
||||
if(object->result == TEST_PASSED) {
|
||||
fprintf(fout, "\"%s\"}", "OK");
|
||||
} else
|
||||
if(object->result == TEST_FAILED) {
|
||||
fprintf(fout, "\"%s\"}", "FAIL");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Start a test
|
||||
void start_test(tTestSection* section, const char* code, const char* description) {
|
||||
tTest* test = NULL;
|
||||
|
||||
assert(section != NULL);
|
||||
assert(code != NULL);
|
||||
assert(description != NULL);
|
||||
#ifdef PRINT_TEST_PROGRESS
|
||||
printf("\n[START] ==> Running test [%s] - %s\n", code, description);
|
||||
#endif // PRINT_TEST_PROGRESS
|
||||
testSection_addTest(section, code, description, TEST_RUNNING);
|
||||
|
||||
test = testSection_getTest(section, code);
|
||||
assert(test != NULL);
|
||||
}
|
||||
|
||||
// Finish a test
|
||||
void end_test(tTestSection* section, const char* code, bool passed) {
|
||||
tTest* test = NULL;
|
||||
assert(section != NULL);
|
||||
assert(code != NULL);
|
||||
|
||||
test = testSection_getTest(section, code);
|
||||
assert(test != NULL);
|
||||
|
||||
if(passed) {
|
||||
#ifdef PRINT_TEST_PROGRESS
|
||||
printf("\n[OK] ==> Finished test [%s] - %s\n", test->code, test->description);
|
||||
#endif // PRINT_TEST_PROGRESS
|
||||
test_updateTest(test, TEST_PASSED);
|
||||
} else {
|
||||
#ifdef PRINT_TEST_PROGRESS
|
||||
printf("\n[FAIL] ==> Finished test [%s] - %s\n", test->code, test->description);
|
||||
#endif // PRINT_TEST_PROGRESS
|
||||
test_updateTest(test, TEST_FAILED);
|
||||
}
|
||||
}
|
||||
Reference in a new issue